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);
7158 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7159 if(ent->flags & RENDER_EQUALIZE)
7161 // first fix up ambient lighting...
7162 if(r_equalize_entities_minambient.value > 0)
7164 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7167 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7168 if(fa < r_equalize_entities_minambient.value * fd)
7171 // fa'/fd' = minambient
7172 // fa'+0.25*fd' = fa+0.25*fd
7174 // fa' = fd' * minambient
7175 // fd'*(0.25+minambient) = fa+0.25*fd
7177 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7178 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7180 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7181 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
7182 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7183 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7188 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7190 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
7191 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
7194 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
7195 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
7196 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7202 VectorSet(ent->modellight_ambient, 1, 1, 1);
7204 // move the light direction into modelspace coordinates for lighting code
7205 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7206 if(VectorLength2(ent->modellight_lightdir) == 0)
7207 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7208 VectorNormalize(ent->modellight_lightdir);
7212 #define MAX_LINEOFSIGHTTRACES 64
7214 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7217 vec3_t boxmins, boxmaxs;
7220 dp_model_t *model = r_refdef.scene.worldmodel;
7222 if (!model || !model->brush.TraceLineOfSight)
7225 // expand the box a little
7226 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7227 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7228 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7229 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7230 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7231 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7233 // return true if eye is inside enlarged box
7234 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7238 VectorCopy(eye, start);
7239 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7240 if (model->brush.TraceLineOfSight(model, start, end))
7243 // try various random positions
7244 for (i = 0;i < numsamples;i++)
7246 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7247 if (model->brush.TraceLineOfSight(model, start, end))
7255 static void R_View_UpdateEntityVisible (void)
7260 entity_render_t *ent;
7262 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7263 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7264 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
7265 : RENDER_EXTERIORMODEL;
7266 if (!r_drawviewmodel.integer)
7267 renderimask |= RENDER_VIEWMODEL;
7268 if (!r_drawexteriormodel.integer)
7269 renderimask |= RENDER_EXTERIORMODEL;
7270 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
7272 // worldmodel can check visibility
7273 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
7274 for (i = 0;i < r_refdef.scene.numentities;i++)
7276 ent = r_refdef.scene.entities[i];
7277 if (!(ent->flags & renderimask))
7278 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)))
7279 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))
7280 r_refdef.viewcache.entityvisible[i] = true;
7282 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
7283 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
7285 for (i = 0;i < r_refdef.scene.numentities;i++)
7287 ent = r_refdef.scene.entities[i];
7288 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
7290 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
7292 continue; // temp entities do pvs only
7293 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
7294 ent->last_trace_visibility = realtime;
7295 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
7296 r_refdef.viewcache.entityvisible[i] = 0;
7303 // no worldmodel or it can't check visibility
7304 for (i = 0;i < r_refdef.scene.numentities;i++)
7306 ent = r_refdef.scene.entities[i];
7307 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));
7312 /// only used if skyrendermasked, and normally returns false
7313 int R_DrawBrushModelsSky (void)
7316 entity_render_t *ent;
7319 for (i = 0;i < r_refdef.scene.numentities;i++)
7321 if (!r_refdef.viewcache.entityvisible[i])
7323 ent = r_refdef.scene.entities[i];
7324 if (!ent->model || !ent->model->DrawSky)
7326 ent->model->DrawSky(ent);
7332 static void R_DrawNoModel(entity_render_t *ent);
7333 static void R_DrawModels(void)
7336 entity_render_t *ent;
7338 for (i = 0;i < r_refdef.scene.numentities;i++)
7340 if (!r_refdef.viewcache.entityvisible[i])
7342 ent = r_refdef.scene.entities[i];
7343 r_refdef.stats.entities++;
7344 if (ent->model && ent->model->Draw != NULL)
7345 ent->model->Draw(ent);
7351 static void R_DrawModelsDepth(void)
7354 entity_render_t *ent;
7356 for (i = 0;i < r_refdef.scene.numentities;i++)
7358 if (!r_refdef.viewcache.entityvisible[i])
7360 ent = r_refdef.scene.entities[i];
7361 if (ent->model && ent->model->DrawDepth != NULL)
7362 ent->model->DrawDepth(ent);
7366 static void R_DrawModelsDebug(void)
7369 entity_render_t *ent;
7371 for (i = 0;i < r_refdef.scene.numentities;i++)
7373 if (!r_refdef.viewcache.entityvisible[i])
7375 ent = r_refdef.scene.entities[i];
7376 if (ent->model && ent->model->DrawDebug != NULL)
7377 ent->model->DrawDebug(ent);
7381 static void R_DrawModelsAddWaterPlanes(void)
7384 entity_render_t *ent;
7386 for (i = 0;i < r_refdef.scene.numentities;i++)
7388 if (!r_refdef.viewcache.entityvisible[i])
7390 ent = r_refdef.scene.entities[i];
7391 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
7392 ent->model->DrawAddWaterPlanes(ent);
7396 static void R_View_SetFrustum(const int *scissor)
7399 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
7400 vec3_t forward, left, up, origin, v;
7404 // flipped x coordinates (because x points left here)
7405 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
7406 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
7408 // non-flipped y coordinates
7409 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7410 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7413 // we can't trust r_refdef.view.forward and friends in reflected scenes
7414 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
7417 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
7418 r_refdef.view.frustum[0].normal[1] = 0 - 0;
7419 r_refdef.view.frustum[0].normal[2] = -1 - 0;
7420 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
7421 r_refdef.view.frustum[1].normal[1] = 0 + 0;
7422 r_refdef.view.frustum[1].normal[2] = -1 + 0;
7423 r_refdef.view.frustum[2].normal[0] = 0 - 0;
7424 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
7425 r_refdef.view.frustum[2].normal[2] = -1 - 0;
7426 r_refdef.view.frustum[3].normal[0] = 0 + 0;
7427 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
7428 r_refdef.view.frustum[3].normal[2] = -1 + 0;
7432 zNear = r_refdef.nearclip;
7433 nudge = 1.0 - 1.0 / (1<<23);
7434 r_refdef.view.frustum[4].normal[0] = 0 - 0;
7435 r_refdef.view.frustum[4].normal[1] = 0 - 0;
7436 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7437 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
7438 r_refdef.view.frustum[5].normal[0] = 0 + 0;
7439 r_refdef.view.frustum[5].normal[1] = 0 + 0;
7440 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7441 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7447 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
7448 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
7449 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
7450 r_refdef.view.frustum[0].dist = m[15] - m[12];
7452 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
7453 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
7454 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
7455 r_refdef.view.frustum[1].dist = m[15] + m[12];
7457 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
7458 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
7459 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
7460 r_refdef.view.frustum[2].dist = m[15] - m[13];
7462 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
7463 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
7464 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
7465 r_refdef.view.frustum[3].dist = m[15] + m[13];
7467 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
7468 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
7469 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
7470 r_refdef.view.frustum[4].dist = m[15] - m[14];
7472 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
7473 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
7474 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
7475 r_refdef.view.frustum[5].dist = m[15] + m[14];
7478 if (r_refdef.view.useperspective)
7480 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
7481 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]);
7482 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]);
7483 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]);
7484 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]);
7486 // then the normals from the corners relative to origin
7487 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
7488 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
7489 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
7490 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
7492 // in a NORMAL view, forward cross left == up
7493 // in a REFLECTED view, forward cross left == down
7494 // so our cross products above need to be adjusted for a left handed coordinate system
7495 CrossProduct(forward, left, v);
7496 if(DotProduct(v, up) < 0)
7498 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
7499 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
7500 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
7501 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
7504 // Leaving those out was a mistake, those were in the old code, and they
7505 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
7506 // I couldn't reproduce it after adding those normalizations. --blub
7507 VectorNormalize(r_refdef.view.frustum[0].normal);
7508 VectorNormalize(r_refdef.view.frustum[1].normal);
7509 VectorNormalize(r_refdef.view.frustum[2].normal);
7510 VectorNormalize(r_refdef.view.frustum[3].normal);
7512 // make the corners absolute
7513 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
7514 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
7515 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
7516 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
7519 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7521 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
7522 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
7523 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
7524 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
7525 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7529 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
7530 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
7531 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
7532 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
7533 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7534 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
7535 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
7536 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
7537 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
7538 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7540 r_refdef.view.numfrustumplanes = 5;
7542 if (r_refdef.view.useclipplane)
7544 r_refdef.view.numfrustumplanes = 6;
7545 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
7548 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7549 PlaneClassify(r_refdef.view.frustum + i);
7551 // LordHavoc: note to all quake engine coders, Quake had a special case
7552 // for 90 degrees which assumed a square view (wrong), so I removed it,
7553 // Quake2 has it disabled as well.
7555 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
7556 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
7557 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
7558 //PlaneClassify(&frustum[0]);
7560 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
7561 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
7562 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
7563 //PlaneClassify(&frustum[1]);
7565 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
7566 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
7567 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
7568 //PlaneClassify(&frustum[2]);
7570 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
7571 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
7572 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
7573 //PlaneClassify(&frustum[3]);
7576 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
7577 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
7578 //PlaneClassify(&frustum[4]);
7581 void R_View_UpdateWithScissor(const int *myscissor)
7583 R_Main_ResizeViewCache();
7584 R_View_SetFrustum(myscissor);
7585 R_View_WorldVisibility(r_refdef.view.useclipplane);
7586 R_View_UpdateEntityVisible();
7587 R_View_UpdateEntityLighting();
7590 void R_View_Update(void)
7592 R_Main_ResizeViewCache();
7593 R_View_SetFrustum(NULL);
7594 R_View_WorldVisibility(r_refdef.view.useclipplane);
7595 R_View_UpdateEntityVisible();
7596 R_View_UpdateEntityLighting();
7599 void R_SetupView(qboolean allowwaterclippingplane)
7601 const float *customclipplane = NULL;
7603 if (r_refdef.view.useclipplane && allowwaterclippingplane)
7605 // LordHavoc: couldn't figure out how to make this approach the
7606 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
7607 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
7608 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
7609 dist = r_refdef.view.clipplane.dist;
7610 plane[0] = r_refdef.view.clipplane.normal[0];
7611 plane[1] = r_refdef.view.clipplane.normal[1];
7612 plane[2] = r_refdef.view.clipplane.normal[2];
7614 customclipplane = plane;
7617 if (!r_refdef.view.useperspective)
7618 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);
7619 else if (vid.stencil && r_useinfinitefarclip.integer)
7620 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);
7622 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);
7623 R_SetViewport(&r_refdef.view.viewport);
7626 void R_EntityMatrix(const matrix4x4_t *matrix)
7628 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
7630 gl_modelmatrixchanged = false;
7631 gl_modelmatrix = *matrix;
7632 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
7633 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
7634 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
7635 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
7637 switch(vid.renderpath)
7639 case RENDERPATH_GL20:
7640 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
7641 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
7642 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7644 case RENDERPATH_CGGL:
7647 if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
7648 if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
7649 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7652 case RENDERPATH_GL13:
7653 case RENDERPATH_GL11:
7654 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7660 void R_ResetViewRendering2D(void)
7662 r_viewport_t viewport;
7665 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
7666 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);
7667 R_SetViewport(&viewport);
7668 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
7669 GL_Color(1, 1, 1, 1);
7670 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7671 GL_BlendFunc(GL_ONE, GL_ZERO);
7672 GL_AlphaTest(false);
7673 GL_ScissorTest(false);
7674 GL_DepthMask(false);
7675 GL_DepthRange(0, 1);
7676 GL_DepthTest(false);
7677 R_EntityMatrix(&identitymatrix);
7678 R_Mesh_ResetTextureState();
7679 GL_PolygonOffset(0, 0);
7680 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7681 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7682 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7683 qglStencilMask(~0);CHECKGLERROR
7684 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7685 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7686 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
7689 void R_ResetViewRendering3D(void)
7694 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7695 GL_Color(1, 1, 1, 1);
7696 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7697 GL_BlendFunc(GL_ONE, GL_ZERO);
7698 GL_AlphaTest(false);
7699 GL_ScissorTest(true);
7701 GL_DepthRange(0, 1);
7703 R_EntityMatrix(&identitymatrix);
7704 R_Mesh_ResetTextureState();
7705 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7706 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7707 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7708 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7709 qglStencilMask(~0);CHECKGLERROR
7710 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7711 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7712 GL_CullFace(r_refdef.view.cullface_back);
7717 R_RenderView_UpdateViewVectors
7720 static void R_RenderView_UpdateViewVectors(void)
7722 // break apart the view matrix into vectors for various purposes
7723 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
7724 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
7725 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
7726 VectorNegate(r_refdef.view.left, r_refdef.view.right);
7727 // make an inverted copy of the view matrix for tracking sprites
7728 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
7731 void R_RenderScene(void);
7732 void R_RenderWaterPlanes(void);
7734 static void R_Water_StartFrame(void)
7737 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
7738 r_waterstate_waterplane_t *p;
7740 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
7743 switch(vid.renderpath)
7745 case RENDERPATH_GL20:
7746 case RENDERPATH_CGGL:
7748 case RENDERPATH_GL13:
7749 case RENDERPATH_GL11:
7753 // set waterwidth and waterheight to the water resolution that will be
7754 // used (often less than the screen resolution for faster rendering)
7755 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
7756 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
7758 // calculate desired texture sizes
7759 // can't use water if the card does not support the texture size
7760 if (!r_water.integer || r_showsurfaces.integer)
7761 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
7762 else if (vid.support.arb_texture_non_power_of_two)
7764 texturewidth = waterwidth;
7765 textureheight = waterheight;
7766 camerawidth = waterwidth;
7767 cameraheight = waterheight;
7771 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
7772 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
7773 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
7774 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
7777 // allocate textures as needed
7778 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
7780 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7781 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
7783 if (p->texture_refraction)
7784 R_FreeTexture(p->texture_refraction);
7785 p->texture_refraction = NULL;
7786 if (p->texture_reflection)
7787 R_FreeTexture(p->texture_reflection);
7788 p->texture_reflection = NULL;
7789 if (p->texture_camera)
7790 R_FreeTexture(p->texture_camera);
7791 p->texture_camera = NULL;
7793 memset(&r_waterstate, 0, sizeof(r_waterstate));
7794 r_waterstate.texturewidth = texturewidth;
7795 r_waterstate.textureheight = textureheight;
7796 r_waterstate.camerawidth = camerawidth;
7797 r_waterstate.cameraheight = cameraheight;
7800 if (r_waterstate.texturewidth)
7802 r_waterstate.enabled = true;
7804 // when doing a reduced render (HDR) we want to use a smaller area
7805 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
7806 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
7808 // set up variables that will be used in shader setup
7809 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7810 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7811 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7812 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7815 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7816 r_waterstate.numwaterplanes = 0;
7819 void R_Water_AddWaterPlane(msurface_t *surface)
7821 int triangleindex, planeindex;
7828 r_waterstate_waterplane_t *p;
7829 texture_t *t = R_GetCurrentTexture(surface->texture);
7830 cam_ent = t->camera_entity;
7831 if(!(t->currentmaterialflags & MATERIALFLAG_CAMERA))
7834 // just use the first triangle with a valid normal for any decisions
7835 VectorClear(normal);
7836 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
7838 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
7839 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
7840 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
7841 TriangleNormal(vert[0], vert[1], vert[2], normal);
7842 if (VectorLength2(normal) >= 0.001)
7846 VectorCopy(normal, plane.normal);
7847 VectorNormalize(plane.normal);
7848 plane.dist = DotProduct(vert[0], plane.normal);
7849 PlaneClassify(&plane);
7850 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
7852 // skip backfaces (except if nocullface is set)
7853 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
7855 VectorNegate(plane.normal, plane.normal);
7857 PlaneClassify(&plane);
7861 // find a matching plane if there is one
7862 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7863 if(p->camera_entity == t->camera_entity)
7864 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
7866 if (planeindex >= r_waterstate.maxwaterplanes)
7867 return; // nothing we can do, out of planes
7869 // if this triangle does not fit any known plane rendered this frame, add one
7870 if (planeindex >= r_waterstate.numwaterplanes)
7872 // store the new plane
7873 r_waterstate.numwaterplanes++;
7875 // clear materialflags and pvs
7876 p->materialflags = 0;
7877 p->pvsvalid = false;
7878 p->camera_entity = t->camera_entity;
7879 VectorCopy(surface->mins, p->mins);
7880 VectorCopy(surface->maxs, p->maxs);
7885 p->mins[0] = min(p->mins[0], surface->mins[0]);
7886 p->mins[1] = min(p->mins[1], surface->mins[1]);
7887 p->mins[2] = min(p->mins[2], surface->mins[2]);
7888 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
7889 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
7890 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
7892 // merge this surface's materialflags into the waterplane
7893 p->materialflags |= t->currentmaterialflags;
7894 if(!(p->materialflags & MATERIALFLAG_CAMERA))
7896 // merge this surface's PVS into the waterplane
7897 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
7898 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
7899 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
7901 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
7907 static void R_Water_ProcessPlanes(void)
7910 r_refdef_view_t originalview;
7911 r_refdef_view_t myview;
7913 r_waterstate_waterplane_t *p;
7916 originalview = r_refdef.view;
7918 // make sure enough textures are allocated
7919 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7921 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7923 if (!p->texture_refraction)
7924 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);
7925 if (!p->texture_refraction)
7928 else if (p->materialflags & MATERIALFLAG_CAMERA)
7930 if (!p->texture_camera)
7931 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);
7932 if (!p->texture_camera)
7936 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7938 if (!p->texture_reflection)
7939 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);
7940 if (!p->texture_reflection)
7946 r_refdef.view = originalview;
7947 r_refdef.view.showdebug = false;
7948 r_refdef.view.width = r_waterstate.waterwidth;
7949 r_refdef.view.height = r_waterstate.waterheight;
7950 r_refdef.view.useclipplane = true;
7951 myview = r_refdef.view;
7952 r_waterstate.renderingscene = true;
7953 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7955 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7957 r_refdef.view = myview;
7958 if(r_water_scissormode.integer)
7961 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
7962 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
7965 // render reflected scene and copy into texture
7966 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
7967 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
7968 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
7969 r_refdef.view.clipplane = p->plane;
7971 // reverse the cullface settings for this render
7972 r_refdef.view.cullface_front = GL_FRONT;
7973 r_refdef.view.cullface_back = GL_BACK;
7974 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
7976 r_refdef.view.usecustompvs = true;
7978 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7980 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7983 R_ResetViewRendering3D();
7984 R_ClearScreen(r_refdef.fogenabled);
7985 if(r_water_scissormode.integer & 2)
7986 R_View_UpdateWithScissor(myscissor);
7989 if(r_water_scissormode.integer & 1)
7990 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
7993 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);
7996 // render the normal view scene and copy into texture
7997 // (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)
7998 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8000 r_refdef.view = myview;
8001 if(r_water_scissormode.integer)
8004 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8005 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8008 r_waterstate.renderingrefraction = true;
8010 r_refdef.view.clipplane = p->plane;
8011 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8012 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8014 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8016 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8017 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8018 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8019 R_RenderView_UpdateViewVectors();
8020 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8022 r_refdef.view.usecustompvs = true;
8023 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);
8027 PlaneClassify(&r_refdef.view.clipplane);
8029 R_ResetViewRendering3D();
8030 R_ClearScreen(r_refdef.fogenabled);
8031 if(r_water_scissormode.integer & 2)
8032 R_View_UpdateWithScissor(myscissor);
8035 if(r_water_scissormode.integer & 1)
8036 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8039 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);
8040 r_waterstate.renderingrefraction = false;
8042 else if (p->materialflags & MATERIALFLAG_CAMERA)
8044 r_refdef.view = myview;
8046 r_refdef.view.clipplane = p->plane;
8047 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8048 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8050 r_refdef.view.width = r_waterstate.camerawidth;
8051 r_refdef.view.height = r_waterstate.cameraheight;
8052 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8053 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8055 if(p->camera_entity)
8057 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8058 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8061 // note: all of the view is used for displaying... so
8062 // there is no use in scissoring
8064 // reverse the cullface settings for this render
8065 r_refdef.view.cullface_front = GL_FRONT;
8066 r_refdef.view.cullface_back = GL_BACK;
8067 // also reverse the view matrix
8068 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
8069 R_RenderView_UpdateViewVectors();
8070 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8072 r_refdef.view.usecustompvs = true;
8073 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);
8076 // camera needs no clipplane
8077 r_refdef.view.useclipplane = false;
8079 PlaneClassify(&r_refdef.view.clipplane);
8081 R_ResetViewRendering3D();
8082 R_ClearScreen(r_refdef.fogenabled);
8086 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);
8087 r_waterstate.renderingrefraction = false;
8091 r_waterstate.renderingscene = false;
8092 r_refdef.view = originalview;
8093 R_ResetViewRendering3D();
8094 R_ClearScreen(r_refdef.fogenabled);
8098 r_refdef.view = originalview;
8099 r_waterstate.renderingscene = false;
8100 Cvar_SetValueQuick(&r_water, 0);
8101 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
8105 void R_Bloom_StartFrame(void)
8107 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8109 switch(vid.renderpath)
8111 case RENDERPATH_GL20:
8112 case RENDERPATH_CGGL:
8114 case RENDERPATH_GL13:
8115 case RENDERPATH_GL11:
8119 // set bloomwidth and bloomheight to the bloom resolution that will be
8120 // used (often less than the screen resolution for faster rendering)
8121 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8122 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8123 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8124 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8125 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8127 // calculate desired texture sizes
8128 if (vid.support.arb_texture_non_power_of_two)
8130 screentexturewidth = r_refdef.view.width;
8131 screentextureheight = r_refdef.view.height;
8132 bloomtexturewidth = r_bloomstate.bloomwidth;
8133 bloomtextureheight = r_bloomstate.bloomheight;
8137 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
8138 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
8139 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
8140 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
8143 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))
8145 Cvar_SetValueQuick(&r_hdr, 0);
8146 Cvar_SetValueQuick(&r_bloom, 0);
8147 Cvar_SetValueQuick(&r_motionblur, 0);
8148 Cvar_SetValueQuick(&r_damageblur, 0);
8151 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)))
8152 screentexturewidth = screentextureheight = 0;
8153 if (!r_hdr.integer && !r_bloom.integer)
8154 bloomtexturewidth = bloomtextureheight = 0;
8156 // allocate textures as needed
8157 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8159 if (r_bloomstate.texture_screen)
8160 R_FreeTexture(r_bloomstate.texture_screen);
8161 r_bloomstate.texture_screen = NULL;
8162 r_bloomstate.screentexturewidth = screentexturewidth;
8163 r_bloomstate.screentextureheight = screentextureheight;
8164 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8165 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);
8167 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8169 if (r_bloomstate.texture_bloom)
8170 R_FreeTexture(r_bloomstate.texture_bloom);
8171 r_bloomstate.texture_bloom = NULL;
8172 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8173 r_bloomstate.bloomtextureheight = bloomtextureheight;
8174 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8175 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);
8178 // when doing a reduced render (HDR) we want to use a smaller area
8179 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8180 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8181 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8182 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8183 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8185 // set up a texcoord array for the full resolution screen image
8186 // (we have to keep this around to copy back during final render)
8187 r_bloomstate.screentexcoord2f[0] = 0;
8188 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
8189 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
8190 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
8191 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
8192 r_bloomstate.screentexcoord2f[5] = 0;
8193 r_bloomstate.screentexcoord2f[6] = 0;
8194 r_bloomstate.screentexcoord2f[7] = 0;
8196 // set up a texcoord array for the reduced resolution bloom image
8197 // (which will be additive blended over the screen image)
8198 r_bloomstate.bloomtexcoord2f[0] = 0;
8199 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8200 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8201 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8202 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8203 r_bloomstate.bloomtexcoord2f[5] = 0;
8204 r_bloomstate.bloomtexcoord2f[6] = 0;
8205 r_bloomstate.bloomtexcoord2f[7] = 0;
8207 if (r_hdr.integer || r_bloom.integer)
8209 r_bloomstate.enabled = true;
8210 r_bloomstate.hdr = r_hdr.integer != 0;
8213 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);
8216 void R_Bloom_CopyBloomTexture(float colorscale)
8218 r_refdef.stats.bloom++;
8220 // scale down screen texture to the bloom texture size
8222 R_SetViewport(&r_bloomstate.viewport);
8223 GL_BlendFunc(GL_ONE, GL_ZERO);
8224 GL_Color(colorscale, colorscale, colorscale, 1);
8225 // TODO: optimize with multitexture or GLSL
8226 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
8227 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8228 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8229 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8231 // we now have a bloom image in the framebuffer
8232 // copy it into the bloom image texture for later processing
8233 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);
8234 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8237 void R_Bloom_CopyHDRTexture(void)
8239 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);
8240 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8243 void R_Bloom_MakeTexture(void)
8246 float xoffset, yoffset, r, brighten;
8248 r_refdef.stats.bloom++;
8250 R_ResetViewRendering2D();
8251 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
8252 R_Mesh_ColorPointer(NULL, 0, 0);
8254 // we have a bloom image in the framebuffer
8256 R_SetViewport(&r_bloomstate.viewport);
8258 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
8261 r = bound(0, r_bloom_colorexponent.value / x, 1);
8262 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
8263 GL_Color(r, r, r, 1);
8264 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8265 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
8266 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8267 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8269 // copy the vertically blurred bloom view to a texture
8270 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);
8271 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8274 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
8275 brighten = r_bloom_brighten.value;
8277 brighten *= r_hdr_range.value;
8278 brighten = sqrt(brighten);
8280 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
8281 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8282 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
8284 for (dir = 0;dir < 2;dir++)
8286 // blend on at multiple vertical offsets to achieve a vertical blur
8287 // TODO: do offset blends using GLSL
8288 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
8289 GL_BlendFunc(GL_ONE, GL_ZERO);
8290 for (x = -range;x <= range;x++)
8292 if (!dir){xoffset = 0;yoffset = x;}
8293 else {xoffset = x;yoffset = 0;}
8294 xoffset /= (float)r_bloomstate.bloomtexturewidth;
8295 yoffset /= (float)r_bloomstate.bloomtextureheight;
8296 // compute a texcoord array with the specified x and y offset
8297 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
8298 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8299 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8300 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8301 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8302 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
8303 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
8304 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
8305 // this r value looks like a 'dot' particle, fading sharply to
8306 // black at the edges
8307 // (probably not realistic but looks good enough)
8308 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
8309 //r = brighten/(range*2+1);
8310 r = brighten / (range * 2 + 1);
8312 r *= (1 - x*x/(float)(range*range));
8313 GL_Color(r, r, r, 1);
8314 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8315 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8316 GL_BlendFunc(GL_ONE, GL_ONE);
8319 // copy the vertically blurred bloom view to a texture
8320 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);
8321 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8324 // apply subtract last
8325 // (just like it would be in a GLSL shader)
8326 if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
8328 GL_BlendFunc(GL_ONE, GL_ZERO);
8329 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8330 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
8331 GL_Color(1, 1, 1, 1);
8332 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8333 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8335 GL_BlendFunc(GL_ONE, GL_ONE);
8336 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
8337 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8338 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
8339 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
8340 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8341 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8342 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
8344 // copy the darkened bloom view to a texture
8345 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);
8346 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8350 void R_HDR_RenderBloomTexture(void)
8352 int oldwidth, oldheight;
8353 float oldcolorscale;
8355 oldcolorscale = r_refdef.view.colorscale;
8356 oldwidth = r_refdef.view.width;
8357 oldheight = r_refdef.view.height;
8358 r_refdef.view.width = r_bloomstate.bloomwidth;
8359 r_refdef.view.height = r_bloomstate.bloomheight;
8361 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
8362 // TODO: add exposure compensation features
8363 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
8365 r_refdef.view.showdebug = false;
8366 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
8368 R_ResetViewRendering3D();
8370 R_ClearScreen(r_refdef.fogenabled);
8371 if (r_timereport_active)
8372 R_TimeReport("HDRclear");
8375 if (r_timereport_active)
8376 R_TimeReport("visibility");
8378 // only do secondary renders with HDR if r_hdr is 2 or higher
8379 r_waterstate.numwaterplanes = 0;
8380 if (r_waterstate.enabled && r_hdr.integer >= 2)
8381 R_RenderWaterPlanes();
8383 r_refdef.view.showdebug = true;
8385 r_waterstate.numwaterplanes = 0;
8387 R_ResetViewRendering2D();
8389 R_Bloom_CopyHDRTexture();
8390 R_Bloom_MakeTexture();
8392 // restore the view settings
8393 r_refdef.view.width = oldwidth;
8394 r_refdef.view.height = oldheight;
8395 r_refdef.view.colorscale = oldcolorscale;
8397 R_ResetViewRendering3D();
8399 R_ClearScreen(r_refdef.fogenabled);
8400 if (r_timereport_active)
8401 R_TimeReport("viewclear");
8404 static void R_BlendView(void)
8406 unsigned int permutation;
8407 float uservecs[4][4];
8409 switch (vid.renderpath)
8411 case RENDERPATH_GL20:
8412 case RENDERPATH_CGGL:
8414 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
8415 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
8416 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
8417 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
8418 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
8420 if (r_bloomstate.texture_screen)
8422 // make sure the buffer is available
8423 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
8425 R_ResetViewRendering2D();
8426 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
8427 R_Mesh_ColorPointer(NULL, 0, 0);
8429 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
8431 // declare variables
8433 static float avgspeed;
8435 speed = VectorLength(cl.movement_velocity);
8437 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
8438 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
8440 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
8441 speed = bound(0, speed, 1);
8442 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
8444 // calculate values into a standard alpha
8445 cl.motionbluralpha = 1 - exp(-
8447 (r_motionblur.value * speed / 80)
8449 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
8452 max(0.0001, cl.time - cl.oldtime) // fps independent
8455 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
8456 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
8458 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
8460 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8461 GL_Color(1, 1, 1, cl.motionbluralpha);
8462 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8463 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
8464 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8465 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8469 // copy view into the screen texture
8470 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);
8471 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8473 else if (!r_bloomstate.texture_bloom)
8475 // we may still have to do view tint...
8476 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8478 // apply a color tint to the whole view
8479 R_ResetViewRendering2D();
8480 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
8481 R_Mesh_ColorPointer(NULL, 0, 0);
8482 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8483 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8484 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8485 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8487 break; // no screen processing, no bloom, skip it
8490 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
8492 // render simple bloom effect
8493 // copy the screen and shrink it and darken it for the bloom process
8494 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
8495 // make the bloom texture
8496 R_Bloom_MakeTexture();
8499 #if _MSC_VER >= 1400
8500 #define sscanf sscanf_s
8502 memset(uservecs, 0, sizeof(uservecs));
8503 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
8504 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
8505 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
8506 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
8508 R_ResetViewRendering2D();
8509 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
8510 R_Mesh_ColorPointer(NULL, 0, 0);
8511 GL_Color(1, 1, 1, 1);
8512 GL_BlendFunc(GL_ONE, GL_ZERO);
8513 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
8514 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
8516 switch(vid.renderpath)
8518 case RENDERPATH_GL20:
8519 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
8520 if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
8521 if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
8522 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
8523 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]);
8524 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8525 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]);
8526 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]);
8527 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]);
8528 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]);
8529 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
8530 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8532 case RENDERPATH_CGGL:
8534 R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
8535 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_bloomstate.texture_screen);CHECKCGERROR
8536 if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_bloomstate.texture_bloom );CHECKCGERROR
8537 if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps );CHECKCGERROR
8538 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
8539 if (r_cg_permutation->fp_PixelSize ) cgGLSetParameter2f( r_cg_permutation->fp_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
8540 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
8541 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
8542 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
8543 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
8544 if (r_cg_permutation->fp_Saturation ) cgGLSetParameter1f( r_cg_permutation->fp_Saturation , r_glsl_saturation.value);CHECKCGERROR
8545 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
8551 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8552 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8554 case RENDERPATH_GL13:
8555 case RENDERPATH_GL11:
8556 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8558 // apply a color tint to the whole view
8559 R_ResetViewRendering2D();
8560 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
8561 R_Mesh_ColorPointer(NULL, 0, 0);
8562 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8563 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8564 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8565 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8571 matrix4x4_t r_waterscrollmatrix;
8573 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
8575 if (r_refdef.fog_density)
8577 r_refdef.fogcolor[0] = r_refdef.fog_red;
8578 r_refdef.fogcolor[1] = r_refdef.fog_green;
8579 r_refdef.fogcolor[2] = r_refdef.fog_blue;
8581 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
8582 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
8583 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
8584 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
8588 VectorCopy(r_refdef.fogcolor, fogvec);
8589 // color.rgb *= ContrastBoost * SceneBrightness;
8590 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
8591 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
8592 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
8593 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
8598 void R_UpdateVariables(void)
8602 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
8604 r_refdef.farclip = r_farclip_base.value;
8605 if (r_refdef.scene.worldmodel)
8606 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
8607 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
8609 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
8610 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
8611 r_refdef.polygonfactor = 0;
8612 r_refdef.polygonoffset = 0;
8613 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8614 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8616 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
8617 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
8618 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
8619 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
8620 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
8621 if (FAKELIGHT_ENABLED)
8623 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
8625 if (r_showsurfaces.integer)
8627 r_refdef.scene.rtworld = false;
8628 r_refdef.scene.rtworldshadows = false;
8629 r_refdef.scene.rtdlight = false;
8630 r_refdef.scene.rtdlightshadows = false;
8631 r_refdef.lightmapintensity = 0;
8634 if (gamemode == GAME_NEHAHRA)
8636 if (gl_fogenable.integer)
8638 r_refdef.oldgl_fogenable = true;
8639 r_refdef.fog_density = gl_fogdensity.value;
8640 r_refdef.fog_red = gl_fogred.value;
8641 r_refdef.fog_green = gl_foggreen.value;
8642 r_refdef.fog_blue = gl_fogblue.value;
8643 r_refdef.fog_alpha = 1;
8644 r_refdef.fog_start = 0;
8645 r_refdef.fog_end = gl_skyclip.value;
8646 r_refdef.fog_height = 1<<30;
8647 r_refdef.fog_fadedepth = 128;
8649 else if (r_refdef.oldgl_fogenable)
8651 r_refdef.oldgl_fogenable = false;
8652 r_refdef.fog_density = 0;
8653 r_refdef.fog_red = 0;
8654 r_refdef.fog_green = 0;
8655 r_refdef.fog_blue = 0;
8656 r_refdef.fog_alpha = 0;
8657 r_refdef.fog_start = 0;
8658 r_refdef.fog_end = 0;
8659 r_refdef.fog_height = 1<<30;
8660 r_refdef.fog_fadedepth = 128;
8664 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
8665 r_refdef.fog_start = max(0, r_refdef.fog_start);
8666 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
8668 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
8670 if (r_refdef.fog_density && r_drawfog.integer)
8672 r_refdef.fogenabled = true;
8673 // this is the point where the fog reaches 0.9986 alpha, which we
8674 // consider a good enough cutoff point for the texture
8675 // (0.9986 * 256 == 255.6)
8676 if (r_fog_exp2.integer)
8677 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
8679 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
8680 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
8681 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
8682 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
8683 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
8684 R_BuildFogHeightTexture();
8685 // fog color was already set
8686 // update the fog texture
8687 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)
8688 R_BuildFogTexture();
8689 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
8690 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
8693 r_refdef.fogenabled = false;
8695 switch(vid.renderpath)
8697 case RENDERPATH_GL20:
8698 case RENDERPATH_CGGL:
8699 if(v_glslgamma.integer && !vid_gammatables_trivial)
8701 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
8703 // build GLSL gamma texture
8704 #define RAMPWIDTH 256
8705 unsigned short ramp[RAMPWIDTH * 3];
8706 unsigned char rampbgr[RAMPWIDTH][4];
8709 r_texture_gammaramps_serial = vid_gammatables_serial;
8711 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
8712 for(i = 0; i < RAMPWIDTH; ++i)
8714 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8715 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8716 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
8719 if (r_texture_gammaramps)
8721 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
8725 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
8731 // remove GLSL gamma texture
8734 case RENDERPATH_GL13:
8735 case RENDERPATH_GL11:
8740 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
8741 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
8747 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
8748 if( scenetype != r_currentscenetype ) {
8749 // store the old scenetype
8750 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
8751 r_currentscenetype = scenetype;
8752 // move in the new scene
8753 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
8762 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
8764 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
8765 if( scenetype == r_currentscenetype ) {
8766 return &r_refdef.scene;
8768 return &r_scenes_store[ scenetype ];
8777 void R_RenderView(void)
8779 if (r_timereport_active)
8780 R_TimeReport("start");
8781 r_textureframe++; // used only by R_GetCurrentTexture
8782 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8784 if(R_CompileShader_CheckStaticParms())
8787 if (!r_drawentities.integer)
8788 r_refdef.scene.numentities = 0;
8790 R_AnimCache_ClearCache();
8791 R_FrameData_NewFrame();
8793 if (r_refdef.view.isoverlay)
8795 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
8796 GL_Clear( GL_DEPTH_BUFFER_BIT );
8797 R_TimeReport("depthclear");
8799 r_refdef.view.showdebug = false;
8801 r_waterstate.enabled = false;
8802 r_waterstate.numwaterplanes = 0;
8810 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
8811 return; //Host_Error ("R_RenderView: NULL worldmodel");
8813 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
8815 R_RenderView_UpdateViewVectors();
8817 R_Shadow_UpdateWorldLightSelection();
8819 R_Bloom_StartFrame();
8820 R_Water_StartFrame();
8823 if (r_timereport_active)
8824 R_TimeReport("viewsetup");
8826 R_ResetViewRendering3D();
8828 if (r_refdef.view.clear || r_refdef.fogenabled)
8830 R_ClearScreen(r_refdef.fogenabled);
8831 if (r_timereport_active)
8832 R_TimeReport("viewclear");
8834 r_refdef.view.clear = true;
8836 // this produces a bloom texture to be used in R_BlendView() later
8837 if (r_hdr.integer && r_bloomstate.bloomwidth)
8839 R_HDR_RenderBloomTexture();
8840 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
8841 r_textureframe++; // used only by R_GetCurrentTexture
8844 r_refdef.view.showdebug = true;
8847 if (r_timereport_active)
8848 R_TimeReport("visibility");
8850 r_waterstate.numwaterplanes = 0;
8851 if (r_waterstate.enabled)
8852 R_RenderWaterPlanes();
8855 r_waterstate.numwaterplanes = 0;
8858 if (r_timereport_active)
8859 R_TimeReport("blendview");
8861 GL_Scissor(0, 0, vid.width, vid.height);
8862 GL_ScissorTest(false);
8867 void R_RenderWaterPlanes(void)
8869 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
8871 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
8872 if (r_timereport_active)
8873 R_TimeReport("waterworld");
8876 // don't let sound skip if going slow
8877 if (r_refdef.scene.extraupdate)
8880 R_DrawModelsAddWaterPlanes();
8881 if (r_timereport_active)
8882 R_TimeReport("watermodels");
8884 if (r_waterstate.numwaterplanes)
8886 R_Water_ProcessPlanes();
8887 if (r_timereport_active)
8888 R_TimeReport("waterscenes");
8892 extern void R_DrawLightningBeams (void);
8893 extern void VM_CL_AddPolygonsToMeshQueue (void);
8894 extern void R_DrawPortals (void);
8895 extern cvar_t cl_locs_show;
8896 static void R_DrawLocs(void);
8897 static void R_DrawEntityBBoxes(void);
8898 static void R_DrawModelDecals(void);
8899 extern void R_DrawModelShadows(void);
8900 extern void R_DrawModelShadowMaps(void);
8901 extern cvar_t cl_decals_newsystem;
8902 extern qboolean r_shadow_usingdeferredprepass;
8903 void R_RenderScene(void)
8905 qboolean shadowmapping = false;
8907 if (r_timereport_active)
8908 R_TimeReport("beginscene");
8910 r_refdef.stats.renders++;
8914 // don't let sound skip if going slow
8915 if (r_refdef.scene.extraupdate)
8918 R_MeshQueue_BeginScene();
8922 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);
8924 if (r_timereport_active)
8925 R_TimeReport("skystartframe");
8927 if (cl.csqc_vidvars.drawworld)
8929 // don't let sound skip if going slow
8930 if (r_refdef.scene.extraupdate)
8933 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
8935 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
8936 if (r_timereport_active)
8937 R_TimeReport("worldsky");
8940 if (R_DrawBrushModelsSky() && r_timereport_active)
8941 R_TimeReport("bmodelsky");
8943 if (skyrendermasked && skyrenderlater)
8945 // we have to force off the water clipping plane while rendering sky
8949 if (r_timereport_active)
8950 R_TimeReport("sky");
8954 R_AnimCache_CacheVisibleEntities();
8955 if (r_timereport_active)
8956 R_TimeReport("animation");
8958 R_Shadow_PrepareLights();
8959 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
8960 R_Shadow_PrepareModelShadows();
8961 if (r_timereport_active)
8962 R_TimeReport("preparelights");
8964 if (R_Shadow_ShadowMappingEnabled())
8965 shadowmapping = true;
8967 if (r_shadow_usingdeferredprepass)
8968 R_Shadow_DrawPrepass();
8970 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
8972 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
8973 if (r_timereport_active)
8974 R_TimeReport("worlddepth");
8976 if (r_depthfirst.integer >= 2)
8978 R_DrawModelsDepth();
8979 if (r_timereport_active)
8980 R_TimeReport("modeldepth");
8983 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
8985 R_DrawModelShadowMaps();
8986 R_ResetViewRendering3D();
8987 // don't let sound skip if going slow
8988 if (r_refdef.scene.extraupdate)
8992 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
8994 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
8995 if (r_timereport_active)
8996 R_TimeReport("world");
8999 // don't let sound skip if going slow
9000 if (r_refdef.scene.extraupdate)
9004 if (r_timereport_active)
9005 R_TimeReport("models");
9007 // don't let sound skip if going slow
9008 if (r_refdef.scene.extraupdate)
9011 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9013 R_DrawModelShadows();
9014 R_ResetViewRendering3D();
9015 // don't let sound skip if going slow
9016 if (r_refdef.scene.extraupdate)
9020 if (!r_shadow_usingdeferredprepass)
9022 R_Shadow_DrawLights();
9023 if (r_timereport_active)
9024 R_TimeReport("rtlights");
9027 // don't let sound skip if going slow
9028 if (r_refdef.scene.extraupdate)
9031 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9033 R_DrawModelShadows();
9034 R_ResetViewRendering3D();
9035 // don't let sound skip if going slow
9036 if (r_refdef.scene.extraupdate)
9040 if (cl.csqc_vidvars.drawworld)
9042 if (cl_decals_newsystem.integer)
9044 R_DrawModelDecals();
9045 if (r_timereport_active)
9046 R_TimeReport("modeldecals");
9051 if (r_timereport_active)
9052 R_TimeReport("decals");
9056 if (r_timereport_active)
9057 R_TimeReport("particles");
9060 if (r_timereport_active)
9061 R_TimeReport("explosions");
9063 R_DrawLightningBeams();
9064 if (r_timereport_active)
9065 R_TimeReport("lightning");
9068 VM_CL_AddPolygonsToMeshQueue();
9070 if (r_refdef.view.showdebug)
9072 if (cl_locs_show.integer)
9075 if (r_timereport_active)
9076 R_TimeReport("showlocs");
9079 if (r_drawportals.integer)
9082 if (r_timereport_active)
9083 R_TimeReport("portals");
9086 if (r_showbboxes.value > 0)
9088 R_DrawEntityBBoxes();
9089 if (r_timereport_active)
9090 R_TimeReport("bboxes");
9094 R_MeshQueue_RenderTransparent();
9095 if (r_timereport_active)
9096 R_TimeReport("drawtrans");
9098 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))
9100 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9101 if (r_timereport_active)
9102 R_TimeReport("worlddebug");
9103 R_DrawModelsDebug();
9104 if (r_timereport_active)
9105 R_TimeReport("modeldebug");
9108 if (cl.csqc_vidvars.drawworld)
9110 R_Shadow_DrawCoronas();
9111 if (r_timereport_active)
9112 R_TimeReport("coronas");
9117 GL_DepthTest(false);
9118 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9119 GL_Color(1, 1, 1, 1);
9120 qglBegin(GL_POLYGON);
9121 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
9122 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
9123 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
9124 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
9126 qglBegin(GL_POLYGON);
9127 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]);
9128 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]);
9129 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]);
9130 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]);
9132 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9136 // don't let sound skip if going slow
9137 if (r_refdef.scene.extraupdate)
9140 R_ResetViewRendering2D();
9143 static const unsigned short bboxelements[36] =
9153 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9156 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9158 RSurf_ActiveWorldEntity();
9160 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9161 GL_DepthMask(false);
9162 GL_DepthRange(0, 1);
9163 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9164 R_Mesh_ResetTextureState();
9166 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9167 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9168 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9169 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9170 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9171 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9172 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9173 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9174 R_FillColors(color4f, 8, cr, cg, cb, ca);
9175 if (r_refdef.fogenabled)
9177 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9179 f1 = RSurf_FogVertex(v);
9181 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9182 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9183 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9186 R_Mesh_VertexPointer(vertex3f, 0, 0);
9187 R_Mesh_ColorPointer(color4f, 0, 0);
9188 R_Mesh_ResetTextureState();
9189 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9190 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
9193 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9197 prvm_edict_t *edict;
9198 prvm_prog_t *prog_save = prog;
9200 // this function draws bounding boxes of server entities
9204 GL_CullFace(GL_NONE);
9205 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9209 for (i = 0;i < numsurfaces;i++)
9211 edict = PRVM_EDICT_NUM(surfacelist[i]);
9212 switch ((int)edict->fields.server->solid)
9214 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
9215 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
9216 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
9217 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9218 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
9219 default: Vector4Set(color, 0, 0, 0, 0.50);break;
9221 color[3] *= r_showbboxes.value;
9222 color[3] = bound(0, color[3], 1);
9223 GL_DepthTest(!r_showdisabledepthtest.integer);
9224 GL_CullFace(r_refdef.view.cullface_front);
9225 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
9231 static void R_DrawEntityBBoxes(void)
9234 prvm_edict_t *edict;
9236 prvm_prog_t *prog_save = prog;
9238 // this function draws bounding boxes of server entities
9244 for (i = 0;i < prog->num_edicts;i++)
9246 edict = PRVM_EDICT_NUM(i);
9247 if (edict->priv.server->free)
9249 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
9250 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
9252 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
9254 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
9255 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
9261 static const int nomodelelement3i[24] =
9273 static const unsigned short nomodelelement3s[24] =
9285 static const float nomodelvertex3f[6*3] =
9295 static const float nomodelcolor4f[6*4] =
9297 0.0f, 0.0f, 0.5f, 1.0f,
9298 0.0f, 0.0f, 0.5f, 1.0f,
9299 0.0f, 0.5f, 0.0f, 1.0f,
9300 0.0f, 0.5f, 0.0f, 1.0f,
9301 0.5f, 0.0f, 0.0f, 1.0f,
9302 0.5f, 0.0f, 0.0f, 1.0f
9305 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9311 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);
9313 // this is only called once per entity so numsurfaces is always 1, and
9314 // surfacelist is always {0}, so this code does not handle batches
9316 if (rsurface.ent_flags & RENDER_ADDITIVE)
9318 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
9319 GL_DepthMask(false);
9321 else if (rsurface.colormod[3] < 1)
9323 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9324 GL_DepthMask(false);
9328 GL_BlendFunc(GL_ONE, GL_ZERO);
9331 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
9332 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
9333 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
9334 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
9335 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9336 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
9337 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
9338 R_Mesh_ColorPointer(color4f, 0, 0);
9339 for (i = 0, c = color4f;i < 6;i++, c += 4)
9341 c[0] *= rsurface.colormod[0];
9342 c[1] *= rsurface.colormod[1];
9343 c[2] *= rsurface.colormod[2];
9344 c[3] *= rsurface.colormod[3];
9346 if (r_refdef.fogenabled)
9348 for (i = 0, c = color4f;i < 6;i++, c += 4)
9350 f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
9352 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
9353 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
9354 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
9357 R_Mesh_ResetTextureState();
9358 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
9361 void R_DrawNoModel(entity_render_t *ent)
9364 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
9365 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
9366 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
9368 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
9371 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
9373 vec3_t right1, right2, diff, normal;
9375 VectorSubtract (org2, org1, normal);
9377 // calculate 'right' vector for start
9378 VectorSubtract (r_refdef.view.origin, org1, diff);
9379 CrossProduct (normal, diff, right1);
9380 VectorNormalize (right1);
9382 // calculate 'right' vector for end
9383 VectorSubtract (r_refdef.view.origin, org2, diff);
9384 CrossProduct (normal, diff, right2);
9385 VectorNormalize (right2);
9387 vert[ 0] = org1[0] + width * right1[0];
9388 vert[ 1] = org1[1] + width * right1[1];
9389 vert[ 2] = org1[2] + width * right1[2];
9390 vert[ 3] = org1[0] - width * right1[0];
9391 vert[ 4] = org1[1] - width * right1[1];
9392 vert[ 5] = org1[2] - width * right1[2];
9393 vert[ 6] = org2[0] - width * right2[0];
9394 vert[ 7] = org2[1] - width * right2[1];
9395 vert[ 8] = org2[2] - width * right2[2];
9396 vert[ 9] = org2[0] + width * right2[0];
9397 vert[10] = org2[1] + width * right2[1];
9398 vert[11] = org2[2] + width * right2[2];
9401 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)
9403 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
9404 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
9405 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
9406 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
9407 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
9408 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
9409 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
9410 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
9411 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
9412 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
9413 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
9414 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
9417 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
9422 VectorSet(v, x, y, z);
9423 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
9424 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
9426 if (i == mesh->numvertices)
9428 if (mesh->numvertices < mesh->maxvertices)
9430 VectorCopy(v, vertex3f);
9431 mesh->numvertices++;
9433 return mesh->numvertices;
9439 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
9443 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9444 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9445 e = mesh->element3i + mesh->numtriangles * 3;
9446 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
9448 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
9449 if (mesh->numtriangles < mesh->maxtriangles)
9454 mesh->numtriangles++;
9456 element[1] = element[2];
9460 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
9464 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9465 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9466 e = mesh->element3i + mesh->numtriangles * 3;
9467 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
9469 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
9470 if (mesh->numtriangles < mesh->maxtriangles)
9475 mesh->numtriangles++;
9477 element[1] = element[2];
9481 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
9482 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
9484 int planenum, planenum2;
9487 mplane_t *plane, *plane2;
9489 double temppoints[2][256*3];
9490 // figure out how large a bounding box we need to properly compute this brush
9492 for (w = 0;w < numplanes;w++)
9493 maxdist = max(maxdist, fabs(planes[w].dist));
9494 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
9495 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
9496 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
9500 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
9501 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
9503 if (planenum2 == planenum)
9505 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);
9508 if (tempnumpoints < 3)
9510 // generate elements forming a triangle fan for this polygon
9511 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
9515 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)
9517 texturelayer_t *layer;
9518 layer = t->currentlayers + t->currentnumlayers++;
9520 layer->depthmask = depthmask;
9521 layer->blendfunc1 = blendfunc1;
9522 layer->blendfunc2 = blendfunc2;
9523 layer->texture = texture;
9524 layer->texmatrix = *matrix;
9525 layer->color[0] = r;
9526 layer->color[1] = g;
9527 layer->color[2] = b;
9528 layer->color[3] = a;
9531 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
9533 if(parms[0] == 0 && parms[1] == 0)
9535 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
9536 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
9541 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
9544 index = parms[2] + r_refdef.scene.time * parms[3];
9545 index -= floor(index);
9546 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
9549 case Q3WAVEFUNC_NONE:
9550 case Q3WAVEFUNC_NOISE:
9551 case Q3WAVEFUNC_COUNT:
9554 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
9555 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
9556 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
9557 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
9558 case Q3WAVEFUNC_TRIANGLE:
9560 f = index - floor(index);
9571 f = parms[0] + parms[1] * f;
9572 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
9573 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
9577 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
9582 matrix4x4_t matrix, temp;
9583 switch(tcmod->tcmod)
9587 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9588 matrix = r_waterscrollmatrix;
9590 matrix = identitymatrix;
9592 case Q3TCMOD_ENTITYTRANSLATE:
9593 // this is used in Q3 to allow the gamecode to control texcoord
9594 // scrolling on the entity, which is not supported in darkplaces yet.
9595 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
9597 case Q3TCMOD_ROTATE:
9598 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
9599 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
9600 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
9603 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
9605 case Q3TCMOD_SCROLL:
9606 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
9608 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
9609 w = (int) tcmod->parms[0];
9610 h = (int) tcmod->parms[1];
9611 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
9613 idx = (int) floor(f * w * h);
9614 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
9616 case Q3TCMOD_STRETCH:
9617 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
9618 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
9620 case Q3TCMOD_TRANSFORM:
9621 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
9622 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
9623 VectorSet(tcmat + 6, 0 , 0 , 1);
9624 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
9625 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
9627 case Q3TCMOD_TURBULENT:
9628 // this is handled in the RSurf_PrepareVertices function
9629 matrix = identitymatrix;
9633 Matrix4x4_Concat(texmatrix, &matrix, &temp);
9636 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
9638 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
9639 char name[MAX_QPATH];
9640 skinframe_t *skinframe;
9641 unsigned char pixels[296*194];
9642 strlcpy(cache->name, skinname, sizeof(cache->name));
9643 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
9644 if (developer_loading.integer)
9645 Con_Printf("loading %s\n", name);
9646 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
9647 if (!skinframe || !skinframe->base)
9650 fs_offset_t filesize;
9652 f = FS_LoadFile(name, tempmempool, true, &filesize);
9655 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
9656 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
9660 cache->skinframe = skinframe;
9663 texture_t *R_GetCurrentTexture(texture_t *t)
9666 const entity_render_t *ent = rsurface.entity;
9667 dp_model_t *model = ent->model;
9668 q3shaderinfo_layer_tcmod_t *tcmod;
9670 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
9671 return t->currentframe;
9672 t->update_lastrenderframe = r_textureframe;
9673 t->update_lastrenderentity = (void *)ent;
9675 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
9676 t->camera_entity = ent->entitynumber;
9678 t->camera_entity = 0;
9680 // switch to an alternate material if this is a q1bsp animated material
9682 texture_t *texture = t;
9683 int s = rsurface.ent_skinnum;
9684 if ((unsigned int)s >= (unsigned int)model->numskins)
9686 if (model->skinscenes)
9688 if (model->skinscenes[s].framecount > 1)
9689 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
9691 s = model->skinscenes[s].firstframe;
9694 t = t + s * model->num_surfaces;
9697 // use an alternate animation if the entity's frame is not 0,
9698 // and only if the texture has an alternate animation
9699 if (rsurface.ent_alttextures && t->anim_total[1])
9700 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
9702 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
9704 texture->currentframe = t;
9707 // update currentskinframe to be a qw skin or animation frame
9708 if (rsurface.ent_qwskin >= 0)
9710 i = rsurface.ent_qwskin;
9711 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
9713 r_qwskincache_size = cl.maxclients;
9715 Mem_Free(r_qwskincache);
9716 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
9718 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
9719 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
9720 t->currentskinframe = r_qwskincache[i].skinframe;
9721 if (t->currentskinframe == NULL)
9722 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9724 else if (t->numskinframes >= 2)
9725 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9726 if (t->backgroundnumskinframes >= 2)
9727 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
9729 t->currentmaterialflags = t->basematerialflags;
9730 t->currentalpha = rsurface.colormod[3];
9731 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
9732 t->currentalpha *= r_wateralpha.value;
9733 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
9734 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
9735 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
9736 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
9737 if (!(rsurface.ent_flags & RENDER_LIGHT))
9738 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
9739 else if (FAKELIGHT_ENABLED)
9741 // no modellight if using fakelight for the map
9743 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
9745 // pick a model lighting mode
9746 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
9747 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
9749 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
9751 if (rsurface.ent_flags & RENDER_ADDITIVE)
9752 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9753 else if (t->currentalpha < 1)
9754 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9755 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
9756 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
9757 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
9758 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
9759 if (t->backgroundnumskinframes)
9760 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
9761 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
9763 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
9764 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
9767 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
9768 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
9769 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
9771 // there is no tcmod
9772 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9774 t->currenttexmatrix = r_waterscrollmatrix;
9775 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
9777 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
9779 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
9780 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
9783 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9784 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
9785 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9786 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
9788 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
9789 if (t->currentskinframe->qpixels)
9790 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
9791 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
9792 if (!t->basetexture)
9793 t->basetexture = r_texture_notexture;
9794 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
9795 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
9796 t->nmaptexture = t->currentskinframe->nmap;
9797 if (!t->nmaptexture)
9798 t->nmaptexture = r_texture_blanknormalmap;
9799 t->glosstexture = r_texture_black;
9800 t->glowtexture = t->currentskinframe->glow;
9801 t->fogtexture = t->currentskinframe->fog;
9802 t->reflectmasktexture = t->currentskinframe->reflect;
9803 if (t->backgroundnumskinframes)
9805 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
9806 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
9807 t->backgroundglosstexture = r_texture_black;
9808 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
9809 if (!t->backgroundnmaptexture)
9810 t->backgroundnmaptexture = r_texture_blanknormalmap;
9814 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
9815 t->backgroundnmaptexture = r_texture_blanknormalmap;
9816 t->backgroundglosstexture = r_texture_black;
9817 t->backgroundglowtexture = NULL;
9819 t->specularpower = r_shadow_glossexponent.value;
9820 // TODO: store reference values for these in the texture?
9821 t->specularscale = 0;
9822 if (r_shadow_gloss.integer > 0)
9824 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
9826 if (r_shadow_glossintensity.value > 0)
9828 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
9829 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
9830 t->specularscale = r_shadow_glossintensity.value;
9833 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
9835 t->glosstexture = r_texture_white;
9836 t->backgroundglosstexture = r_texture_white;
9837 t->specularscale = r_shadow_gloss2intensity.value;
9838 t->specularpower = r_shadow_gloss2exponent.value;
9841 t->specularscale *= t->specularscalemod;
9842 t->specularpower *= t->specularpowermod;
9844 // lightmaps mode looks bad with dlights using actual texturing, so turn
9845 // off the colormap and glossmap, but leave the normalmap on as it still
9846 // accurately represents the shading involved
9847 if (gl_lightmaps.integer)
9849 t->basetexture = r_texture_grey128;
9850 t->pantstexture = r_texture_black;
9851 t->shirttexture = r_texture_black;
9852 t->nmaptexture = r_texture_blanknormalmap;
9853 t->glosstexture = r_texture_black;
9854 t->glowtexture = NULL;
9855 t->fogtexture = NULL;
9856 t->reflectmasktexture = NULL;
9857 t->backgroundbasetexture = NULL;
9858 t->backgroundnmaptexture = r_texture_blanknormalmap;
9859 t->backgroundglosstexture = r_texture_black;
9860 t->backgroundglowtexture = NULL;
9861 t->specularscale = 0;
9862 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
9865 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
9866 VectorClear(t->dlightcolor);
9867 t->currentnumlayers = 0;
9868 if (t->currentmaterialflags & MATERIALFLAG_WALL)
9870 int blendfunc1, blendfunc2;
9872 if (t->currentmaterialflags & MATERIALFLAG_ADD)
9874 blendfunc1 = GL_SRC_ALPHA;
9875 blendfunc2 = GL_ONE;
9877 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
9879 blendfunc1 = GL_SRC_ALPHA;
9880 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
9882 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9884 blendfunc1 = t->customblendfunc[0];
9885 blendfunc2 = t->customblendfunc[1];
9889 blendfunc1 = GL_ONE;
9890 blendfunc2 = GL_ZERO;
9892 // don't colormod evilblend textures
9893 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
9894 VectorSet(t->lightmapcolor, 1, 1, 1);
9895 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
9896 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9898 // fullbright is not affected by r_refdef.lightmapintensity
9899 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]);
9900 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9901 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]);
9902 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9903 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]);
9907 vec3_t ambientcolor;
9909 // set the color tint used for lights affecting this surface
9910 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
9912 // q3bsp has no lightmap updates, so the lightstylevalue that
9913 // would normally be baked into the lightmap must be
9914 // applied to the color
9915 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
9916 if (model->type == mod_brushq3)
9917 colorscale *= r_refdef.scene.rtlightstylevalue[0];
9918 colorscale *= r_refdef.lightmapintensity;
9919 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
9920 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
9921 // basic lit geometry
9922 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]);
9923 // add pants/shirt if needed
9924 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9925 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]);
9926 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9927 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]);
9928 // now add ambient passes if needed
9929 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
9931 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]);
9932 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9933 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]);
9934 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9935 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]);
9938 if (t->glowtexture != NULL && !gl_lightmaps.integer)
9939 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]);
9940 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
9942 // if this is opaque use alpha blend which will darken the earlier
9945 // if this is an alpha blended material, all the earlier passes
9946 // were darkened by fog already, so we only need to add the fog
9947 // color ontop through the fog mask texture
9949 // if this is an additive blended material, all the earlier passes
9950 // were darkened by fog already, and we should not add fog color
9951 // (because the background was not darkened, there is no fog color
9952 // that was lost behind it).
9953 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]);
9957 return t->currentframe;
9960 rsurfacestate_t rsurface;
9962 void R_Mesh_ResizeArrays(int newvertices)
9965 if (rsurface.array_size >= newvertices)
9967 if (rsurface.array_modelvertex3f)
9968 Mem_Free(rsurface.array_modelvertex3f);
9969 rsurface.array_size = (newvertices + 1023) & ~1023;
9970 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
9971 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
9972 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
9973 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
9974 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
9975 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
9976 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
9977 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
9978 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
9979 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
9980 rsurface.array_color4f = base + rsurface.array_size * 27;
9981 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
9984 void RSurf_ActiveWorldEntity(void)
9986 dp_model_t *model = r_refdef.scene.worldmodel;
9987 //if (rsurface.entity == r_refdef.scene.worldentity)
9989 rsurface.entity = r_refdef.scene.worldentity;
9990 rsurface.skeleton = NULL;
9991 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
9992 rsurface.ent_skinnum = 0;
9993 rsurface.ent_qwskin = -1;
9994 rsurface.ent_shadertime = 0;
9995 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
9996 if (rsurface.array_size < model->surfmesh.num_vertices)
9997 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9998 rsurface.matrix = identitymatrix;
9999 rsurface.inversematrix = identitymatrix;
10000 rsurface.matrixscale = 1;
10001 rsurface.inversematrixscale = 1;
10002 R_EntityMatrix(&identitymatrix);
10003 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10004 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10005 rsurface.fograngerecip = r_refdef.fograngerecip;
10006 rsurface.fogheightfade = r_refdef.fogheightfade;
10007 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10008 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10009 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10010 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10011 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10012 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10013 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10014 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10015 rsurface.colormod[3] = 1;
10016 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);
10017 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10018 rsurface.frameblend[0].lerp = 1;
10019 rsurface.ent_alttextures = false;
10020 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10021 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10022 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
10023 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
10024 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10025 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10026 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
10027 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10028 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10029 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
10030 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10031 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
10032 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
10033 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10034 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
10035 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
10036 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10037 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
10038 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
10039 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10040 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
10041 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
10042 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10043 rsurface.modelelement3i = model->surfmesh.data_element3i;
10044 rsurface.modelelement3s = model->surfmesh.data_element3s;
10045 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
10046 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
10047 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10048 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
10049 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
10050 rsurface.modelsurfaces = model->data_surfaces;
10051 rsurface.generatedvertex = false;
10052 rsurface.vertex3f = rsurface.modelvertex3f;
10053 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
10054 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
10055 rsurface.svector3f = rsurface.modelsvector3f;
10056 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
10057 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
10058 rsurface.tvector3f = rsurface.modeltvector3f;
10059 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
10060 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
10061 rsurface.normal3f = rsurface.modelnormal3f;
10062 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
10063 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
10064 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
10067 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10069 dp_model_t *model = ent->model;
10070 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10072 rsurface.entity = (entity_render_t *)ent;
10073 rsurface.skeleton = ent->skeleton;
10074 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10075 rsurface.ent_skinnum = ent->skinnum;
10076 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;
10077 rsurface.ent_shadertime = ent->shadertime;
10078 rsurface.ent_flags = ent->flags;
10079 if (rsurface.array_size < model->surfmesh.num_vertices)
10080 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10081 rsurface.matrix = ent->matrix;
10082 rsurface.inversematrix = ent->inversematrix;
10083 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10084 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10085 R_EntityMatrix(&rsurface.matrix);
10086 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10087 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10088 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10089 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10090 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10091 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10092 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10093 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10094 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10095 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10096 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10097 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10098 rsurface.colormod[3] = ent->alpha;
10099 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10100 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10101 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10102 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10103 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10104 if (ent->model->brush.submodel && !prepass)
10106 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10107 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10109 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10111 if (ent->animcache_vertex3f && !r_framedata_failed)
10113 rsurface.modelvertex3f = ent->animcache_vertex3f;
10114 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10115 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10116 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10118 else if (wanttangents)
10120 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10121 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10122 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10123 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10124 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
10126 else if (wantnormals)
10128 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10129 rsurface.modelsvector3f = NULL;
10130 rsurface.modeltvector3f = NULL;
10131 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10132 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
10136 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10137 rsurface.modelsvector3f = NULL;
10138 rsurface.modeltvector3f = NULL;
10139 rsurface.modelnormal3f = NULL;
10140 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
10142 rsurface.modelvertex3f_bufferobject = 0;
10143 rsurface.modelvertex3f_bufferoffset = 0;
10144 rsurface.modelsvector3f_bufferobject = 0;
10145 rsurface.modelsvector3f_bufferoffset = 0;
10146 rsurface.modeltvector3f_bufferobject = 0;
10147 rsurface.modeltvector3f_bufferoffset = 0;
10148 rsurface.modelnormal3f_bufferobject = 0;
10149 rsurface.modelnormal3f_bufferoffset = 0;
10150 rsurface.generatedvertex = true;
10154 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
10155 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
10156 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10157 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10158 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
10159 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10160 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10161 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
10162 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10163 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
10164 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
10165 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10166 rsurface.generatedvertex = false;
10168 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
10169 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
10170 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10171 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
10172 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
10173 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10174 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
10175 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
10176 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10177 rsurface.modelelement3i = model->surfmesh.data_element3i;
10178 rsurface.modelelement3s = model->surfmesh.data_element3s;
10179 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
10180 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
10181 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10182 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
10183 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
10184 rsurface.modelsurfaces = model->data_surfaces;
10185 rsurface.vertex3f = rsurface.modelvertex3f;
10186 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
10187 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
10188 rsurface.svector3f = rsurface.modelsvector3f;
10189 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
10190 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
10191 rsurface.tvector3f = rsurface.modeltvector3f;
10192 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
10193 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
10194 rsurface.normal3f = rsurface.modelnormal3f;
10195 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
10196 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
10197 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
10200 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)
10202 rsurface.entity = r_refdef.scene.worldentity;
10203 rsurface.skeleton = NULL;
10204 rsurface.ent_skinnum = 0;
10205 rsurface.ent_qwskin = -1;
10206 rsurface.ent_shadertime = shadertime;
10207 rsurface.ent_flags = entflags;
10208 rsurface.modelnum_vertices = numvertices;
10209 rsurface.modelnum_triangles = numtriangles;
10210 if (rsurface.array_size < rsurface.modelnum_vertices)
10211 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
10212 rsurface.matrix = *matrix;
10213 rsurface.inversematrix = *inversematrix;
10214 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10215 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10216 R_EntityMatrix(&rsurface.matrix);
10217 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10218 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10219 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10220 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10221 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10222 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10223 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10224 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10225 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10226 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10227 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10228 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
10229 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);
10230 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10231 rsurface.frameblend[0].lerp = 1;
10232 rsurface.ent_alttextures = false;
10233 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10234 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10237 rsurface.modelvertex3f = vertex3f;
10238 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
10239 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
10240 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
10242 else if (wantnormals)
10244 rsurface.modelvertex3f = vertex3f;
10245 rsurface.modelsvector3f = NULL;
10246 rsurface.modeltvector3f = NULL;
10247 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
10251 rsurface.modelvertex3f = vertex3f;
10252 rsurface.modelsvector3f = NULL;
10253 rsurface.modeltvector3f = NULL;
10254 rsurface.modelnormal3f = NULL;
10256 rsurface.modelvertex3f_bufferobject = 0;
10257 rsurface.modelvertex3f_bufferoffset = 0;
10258 rsurface.modelsvector3f_bufferobject = 0;
10259 rsurface.modelsvector3f_bufferoffset = 0;
10260 rsurface.modeltvector3f_bufferobject = 0;
10261 rsurface.modeltvector3f_bufferoffset = 0;
10262 rsurface.modelnormal3f_bufferobject = 0;
10263 rsurface.modelnormal3f_bufferoffset = 0;
10264 rsurface.generatedvertex = true;
10265 rsurface.modellightmapcolor4f = color4f;
10266 rsurface.modellightmapcolor4f_bufferobject = 0;
10267 rsurface.modellightmapcolor4f_bufferoffset = 0;
10268 rsurface.modeltexcoordtexture2f = texcoord2f;
10269 rsurface.modeltexcoordtexture2f_bufferobject = 0;
10270 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
10271 rsurface.modeltexcoordlightmap2f = NULL;
10272 rsurface.modeltexcoordlightmap2f_bufferobject = 0;
10273 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
10274 rsurface.modelelement3i = element3i;
10275 rsurface.modelelement3s = element3s;
10276 rsurface.modelelement3i_bufferobject = 0;
10277 rsurface.modelelement3s_bufferobject = 0;
10278 rsurface.modellightmapoffsets = NULL;
10279 rsurface.modelsurfaces = NULL;
10280 rsurface.vertex3f = rsurface.modelvertex3f;
10281 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
10282 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
10283 rsurface.svector3f = rsurface.modelsvector3f;
10284 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
10285 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
10286 rsurface.tvector3f = rsurface.modeltvector3f;
10287 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
10288 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
10289 rsurface.normal3f = rsurface.modelnormal3f;
10290 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
10291 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
10292 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
10294 if (rsurface.modelnum_vertices && rsurface.modelelement3i)
10296 if ((wantnormals || wanttangents) && !normal3f)
10297 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
10298 if (wanttangents && !svector3f)
10299 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);
10303 float RSurf_FogPoint(const float *v)
10305 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10306 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
10307 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
10308 float FogHeightFade = r_refdef.fogheightfade;
10310 unsigned int fogmasktableindex;
10311 if (r_refdef.fogplaneviewabove)
10312 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10314 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10315 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
10316 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10319 float RSurf_FogVertex(const float *v)
10321 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10322 float FogPlaneViewDist = rsurface.fogplaneviewdist;
10323 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
10324 float FogHeightFade = rsurface.fogheightfade;
10326 unsigned int fogmasktableindex;
10327 if (r_refdef.fogplaneviewabove)
10328 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10330 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10331 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
10332 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10335 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
10336 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
10339 int texturesurfaceindex;
10344 const float *v1, *in_tc;
10346 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
10347 float waveparms[4];
10348 q3shaderinfo_deform_t *deform;
10349 // 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
10350 if (rsurface.generatedvertex)
10352 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
10353 generatenormals = true;
10354 for (i = 0;i < Q3MAXDEFORMS;i++)
10356 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
10358 generatetangents = true;
10359 generatenormals = true;
10361 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
10362 generatenormals = true;
10364 if (generatenormals && !rsurface.modelnormal3f)
10366 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10367 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
10368 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
10369 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
10371 if (generatetangents && !rsurface.modelsvector3f)
10373 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10374 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
10375 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
10376 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10377 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
10378 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
10379 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);
10382 rsurface.vertex3f = rsurface.modelvertex3f;
10383 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
10384 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
10385 rsurface.svector3f = rsurface.modelsvector3f;
10386 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
10387 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
10388 rsurface.tvector3f = rsurface.modeltvector3f;
10389 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
10390 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
10391 rsurface.normal3f = rsurface.modelnormal3f;
10392 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
10393 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
10394 // if vertices are deformed (sprite flares and things in maps, possibly
10395 // water waves, bulges and other deformations), generate them into
10396 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
10397 // (may be static model data or generated data for an animated model, or
10398 // the previous deform pass)
10399 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
10401 switch (deform->deform)
10404 case Q3DEFORM_PROJECTIONSHADOW:
10405 case Q3DEFORM_TEXT0:
10406 case Q3DEFORM_TEXT1:
10407 case Q3DEFORM_TEXT2:
10408 case Q3DEFORM_TEXT3:
10409 case Q3DEFORM_TEXT4:
10410 case Q3DEFORM_TEXT5:
10411 case Q3DEFORM_TEXT6:
10412 case Q3DEFORM_TEXT7:
10413 case Q3DEFORM_NONE:
10415 case Q3DEFORM_AUTOSPRITE:
10416 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
10417 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
10418 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
10419 VectorNormalize(newforward);
10420 VectorNormalize(newright);
10421 VectorNormalize(newup);
10422 // make deformed versions of only the model vertices used by the specified surfaces
10423 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10425 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10426 // a single autosprite surface can contain multiple sprites...
10427 for (j = 0;j < surface->num_vertices - 3;j += 4)
10429 VectorClear(center);
10430 for (i = 0;i < 4;i++)
10431 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
10432 VectorScale(center, 0.25f, center);
10433 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
10434 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
10435 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
10436 for (i = 0;i < 4;i++)
10438 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
10439 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
10442 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);
10443 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);
10445 rsurface.vertex3f = rsurface.array_deformedvertex3f;
10446 rsurface.vertex3f_bufferobject = 0;
10447 rsurface.vertex3f_bufferoffset = 0;
10448 rsurface.svector3f = rsurface.array_deformedsvector3f;
10449 rsurface.svector3f_bufferobject = 0;
10450 rsurface.svector3f_bufferoffset = 0;
10451 rsurface.tvector3f = rsurface.array_deformedtvector3f;
10452 rsurface.tvector3f_bufferobject = 0;
10453 rsurface.tvector3f_bufferoffset = 0;
10454 rsurface.normal3f = rsurface.array_deformednormal3f;
10455 rsurface.normal3f_bufferobject = 0;
10456 rsurface.normal3f_bufferoffset = 0;
10458 case Q3DEFORM_AUTOSPRITE2:
10459 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
10460 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
10461 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
10462 VectorNormalize(newforward);
10463 VectorNormalize(newright);
10464 VectorNormalize(newup);
10465 // make deformed versions of only the model vertices used by the specified surfaces
10466 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10468 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10469 const float *v1, *v2;
10479 memset(shortest, 0, sizeof(shortest));
10480 // a single autosprite surface can contain multiple sprites...
10481 for (j = 0;j < surface->num_vertices - 3;j += 4)
10483 VectorClear(center);
10484 for (i = 0;i < 4;i++)
10485 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
10486 VectorScale(center, 0.25f, center);
10487 // find the two shortest edges, then use them to define the
10488 // axis vectors for rotating around the central axis
10489 for (i = 0;i < 6;i++)
10491 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
10492 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
10494 Debug_PolygonBegin(NULL, 0);
10495 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
10496 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);
10497 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
10498 Debug_PolygonEnd();
10500 l = VectorDistance2(v1, v2);
10501 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
10502 if (v1[2] != v2[2])
10503 l += (1.0f / 1024.0f);
10504 if (shortest[0].length2 > l || i == 0)
10506 shortest[1] = shortest[0];
10507 shortest[0].length2 = l;
10508 shortest[0].v1 = v1;
10509 shortest[0].v2 = v2;
10511 else if (shortest[1].length2 > l || i == 1)
10513 shortest[1].length2 = l;
10514 shortest[1].v1 = v1;
10515 shortest[1].v2 = v2;
10518 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
10519 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
10521 Debug_PolygonBegin(NULL, 0);
10522 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
10523 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);
10524 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
10525 Debug_PolygonEnd();
10527 // this calculates the right vector from the shortest edge
10528 // and the up vector from the edge midpoints
10529 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
10530 VectorNormalize(right);
10531 VectorSubtract(end, start, up);
10532 VectorNormalize(up);
10533 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
10534 VectorSubtract(rsurface.localvieworigin, center, forward);
10535 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
10536 VectorNegate(forward, forward);
10537 VectorReflect(forward, 0, up, forward);
10538 VectorNormalize(forward);
10539 CrossProduct(up, forward, newright);
10540 VectorNormalize(newright);
10542 Debug_PolygonBegin(NULL, 0);
10543 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);
10544 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
10545 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
10546 Debug_PolygonEnd();
10549 Debug_PolygonBegin(NULL, 0);
10550 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
10551 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
10552 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
10553 Debug_PolygonEnd();
10555 // rotate the quad around the up axis vector, this is made
10556 // especially easy by the fact we know the quad is flat,
10557 // so we only have to subtract the center position and
10558 // measure distance along the right vector, and then
10559 // multiply that by the newright vector and add back the
10561 // we also need to subtract the old position to undo the
10562 // displacement from the center, which we do with a
10563 // DotProduct, the subtraction/addition of center is also
10564 // optimized into DotProducts here
10565 l = DotProduct(right, center);
10566 for (i = 0;i < 4;i++)
10568 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
10569 f = DotProduct(right, v1) - l;
10570 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
10573 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);
10574 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);
10576 rsurface.vertex3f = rsurface.array_deformedvertex3f;
10577 rsurface.vertex3f_bufferobject = 0;
10578 rsurface.vertex3f_bufferoffset = 0;
10579 rsurface.svector3f = rsurface.array_deformedsvector3f;
10580 rsurface.svector3f_bufferobject = 0;
10581 rsurface.svector3f_bufferoffset = 0;
10582 rsurface.tvector3f = rsurface.array_deformedtvector3f;
10583 rsurface.tvector3f_bufferobject = 0;
10584 rsurface.tvector3f_bufferoffset = 0;
10585 rsurface.normal3f = rsurface.array_deformednormal3f;
10586 rsurface.normal3f_bufferobject = 0;
10587 rsurface.normal3f_bufferoffset = 0;
10589 case Q3DEFORM_NORMAL:
10590 // deform the normals to make reflections wavey
10591 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10593 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10594 for (j = 0;j < surface->num_vertices;j++)
10597 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
10598 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
10599 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
10600 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
10601 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
10602 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
10603 VectorNormalize(normal);
10605 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);
10607 rsurface.svector3f = rsurface.array_deformedsvector3f;
10608 rsurface.svector3f_bufferobject = 0;
10609 rsurface.svector3f_bufferoffset = 0;
10610 rsurface.tvector3f = rsurface.array_deformedtvector3f;
10611 rsurface.tvector3f_bufferobject = 0;
10612 rsurface.tvector3f_bufferoffset = 0;
10613 rsurface.normal3f = rsurface.array_deformednormal3f;
10614 rsurface.normal3f_bufferobject = 0;
10615 rsurface.normal3f_bufferoffset = 0;
10617 case Q3DEFORM_WAVE:
10618 // deform vertex array to make wavey water and flags and such
10619 waveparms[0] = deform->waveparms[0];
10620 waveparms[1] = deform->waveparms[1];
10621 waveparms[2] = deform->waveparms[2];
10622 waveparms[3] = deform->waveparms[3];
10623 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10624 break; // if wavefunc is a nop, don't make a dynamic vertex array
10625 // this is how a divisor of vertex influence on deformation
10626 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10627 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10628 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10630 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10631 for (j = 0;j < surface->num_vertices;j++)
10633 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
10634 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
10635 // if the wavefunc depends on time, evaluate it per-vertex
10638 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
10639 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10641 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
10644 rsurface.vertex3f = rsurface.array_deformedvertex3f;
10645 rsurface.vertex3f_bufferobject = 0;
10646 rsurface.vertex3f_bufferoffset = 0;
10648 case Q3DEFORM_BULGE:
10649 // deform vertex array to make the surface have moving bulges
10650 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10652 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10653 for (j = 0;j < surface->num_vertices;j++)
10655 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
10656 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
10659 rsurface.vertex3f = rsurface.array_deformedvertex3f;
10660 rsurface.vertex3f_bufferobject = 0;
10661 rsurface.vertex3f_bufferoffset = 0;
10663 case Q3DEFORM_MOVE:
10664 // deform vertex array
10665 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10666 break; // if wavefunc is a nop, don't make a dynamic vertex array
10667 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10668 VectorScale(deform->parms, scale, waveparms);
10669 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10671 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10672 for (j = 0;j < surface->num_vertices;j++)
10673 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
10675 rsurface.vertex3f = rsurface.array_deformedvertex3f;
10676 rsurface.vertex3f_bufferobject = 0;
10677 rsurface.vertex3f_bufferoffset = 0;
10681 // generate texcoords based on the chosen texcoord source
10682 switch(rsurface.texture->tcgen.tcgen)
10685 case Q3TCGEN_TEXTURE:
10686 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
10687 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
10688 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
10690 case Q3TCGEN_LIGHTMAP:
10691 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
10692 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
10693 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
10695 case Q3TCGEN_VECTOR:
10696 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10698 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10699 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)
10701 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
10702 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
10705 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
10706 rsurface.texcoordtexture2f_bufferobject = 0;
10707 rsurface.texcoordtexture2f_bufferoffset = 0;
10709 case Q3TCGEN_ENVIRONMENT:
10710 // make environment reflections using a spheremap
10711 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10713 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10714 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
10715 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
10716 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
10717 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
10719 // identical to Q3A's method, but executed in worldspace so
10720 // carried models can be shiny too
10722 float viewer[3], d, reflected[3], worldreflected[3];
10724 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
10725 // VectorNormalize(viewer);
10727 d = DotProduct(normal, viewer);
10729 reflected[0] = normal[0]*2*d - viewer[0];
10730 reflected[1] = normal[1]*2*d - viewer[1];
10731 reflected[2] = normal[2]*2*d - viewer[2];
10732 // note: this is proportinal to viewer, so we can normalize later
10734 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10735 VectorNormalize(worldreflected);
10737 // note: this sphere map only uses world x and z!
10738 // so positive and negative y will LOOK THE SAME.
10739 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
10740 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
10743 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
10744 rsurface.texcoordtexture2f_bufferobject = 0;
10745 rsurface.texcoordtexture2f_bufferoffset = 0;
10748 // the only tcmod that needs software vertex processing is turbulent, so
10749 // check for it here and apply the changes if needed
10750 // and we only support that as the first one
10751 // (handling a mixture of turbulent and other tcmods would be problematic
10752 // without punting it entirely to a software path)
10753 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10755 amplitude = rsurface.texture->tcmods[0].parms[1];
10756 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
10757 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10759 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10760 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)
10762 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10763 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10766 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
10767 rsurface.texcoordtexture2f_bufferobject = 0;
10768 rsurface.texcoordtexture2f_bufferoffset = 0;
10770 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
10771 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
10772 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
10773 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
10776 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10779 const msurface_t *surface = texturesurfacelist[0];
10780 const msurface_t *surface2;
10785 // TODO: lock all array ranges before render, rather than on each surface
10786 if (texturenumsurfaces == 1)
10787 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);
10788 else if (r_batchmode.integer == 2)
10790 #define MAXBATCHTRIANGLES 65536
10791 int batchtriangles = 0;
10792 static int batchelements[MAXBATCHTRIANGLES*3];
10793 for (i = 0;i < texturenumsurfaces;i = j)
10795 surface = texturesurfacelist[i];
10797 if (surface->num_triangles > MAXBATCHTRIANGLES)
10799 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);
10802 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10803 batchtriangles = surface->num_triangles;
10804 firstvertex = surface->num_firstvertex;
10805 endvertex = surface->num_firstvertex + surface->num_vertices;
10806 for (;j < texturenumsurfaces;j++)
10808 surface2 = texturesurfacelist[j];
10809 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10811 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10812 batchtriangles += surface2->num_triangles;
10813 firstvertex = min(firstvertex, surface2->num_firstvertex);
10814 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10816 surface2 = texturesurfacelist[j-1];
10817 numvertices = endvertex - firstvertex;
10818 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10821 else if (r_batchmode.integer == 1)
10823 for (i = 0;i < texturenumsurfaces;i = j)
10825 surface = texturesurfacelist[i];
10826 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10827 if (texturesurfacelist[j] != surface2)
10829 surface2 = texturesurfacelist[j-1];
10830 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
10831 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
10832 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10837 for (i = 0;i < texturenumsurfaces;i++)
10839 surface = texturesurfacelist[i];
10840 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);
10845 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
10847 switch(vid.renderpath)
10849 case RENDERPATH_CGGL:
10851 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
10852 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
10855 case RENDERPATH_GL20:
10856 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
10857 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
10859 case RENDERPATH_GL13:
10860 case RENDERPATH_GL11:
10861 R_Mesh_TexBind(0, surface->lightmaptexture);
10866 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
10868 // pick the closest matching water plane and bind textures
10869 int planeindex, vertexindex;
10873 r_waterstate_waterplane_t *p, *bestp;
10876 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
10878 if(p->camera_entity != rsurface.texture->camera_entity)
10881 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
10883 Matrix4x4_Transform(&rsurface.matrix, v, vert);
10884 d += fabs(PlaneDiff(vert, &p->plane));
10886 if (bestd > d || !bestp)
10892 switch(vid.renderpath)
10894 case RENDERPATH_CGGL:
10896 if (r_cg_permutation->fp_Texture_Refraction) {CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR}
10897 else if (r_cg_permutation->fp_Texture_First) {CG_BindTexture(r_cg_permutation->fp_Texture_First, bestp ? bestp->texture_camera : r_texture_black);CHECKCGERROR}
10898 if (r_cg_permutation->fp_Texture_Reflection) {CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR}
10901 case RENDERPATH_GL20:
10902 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
10903 else if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST, bestp ? bestp->texture_camera : r_texture_black);
10904 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
10906 case RENDERPATH_GL13:
10907 case RENDERPATH_GL11:
10912 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10915 const msurface_t *surface;
10916 if (r_waterstate.renderingscene)
10918 for (i = 0;i < texturenumsurfaces;i++)
10920 surface = texturesurfacelist[i];
10921 RSurf_BindLightmapForSurface(surface);
10922 RSurf_BindReflectionForSurface(surface);
10923 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);
10927 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10931 const msurface_t *surface = texturesurfacelist[0];
10932 const msurface_t *surface2;
10937 if (texturenumsurfaces == 1)
10939 RSurf_BindLightmapForSurface(surface);
10940 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);
10942 else if (r_batchmode.integer == 2)
10944 int batchtriangles = 0;
10945 static int batchelements[MAXBATCHTRIANGLES*3];
10946 for (i = 0;i < texturenumsurfaces;i = j)
10948 surface = texturesurfacelist[i];
10949 RSurf_BindLightmapForSurface(surface);
10951 if (surface->num_triangles > MAXBATCHTRIANGLES)
10953 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);
10956 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10957 batchtriangles = surface->num_triangles;
10958 firstvertex = surface->num_firstvertex;
10959 endvertex = surface->num_firstvertex + surface->num_vertices;
10960 for (;j < texturenumsurfaces;j++)
10962 surface2 = texturesurfacelist[j];
10963 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10965 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10966 batchtriangles += surface2->num_triangles;
10967 firstvertex = min(firstvertex, surface2->num_firstvertex);
10968 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10970 surface2 = texturesurfacelist[j-1];
10971 numvertices = endvertex - firstvertex;
10972 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10975 else if (r_batchmode.integer == 1)
10978 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
10979 for (i = 0;i < texturenumsurfaces;i = j)
10981 surface = texturesurfacelist[i];
10982 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10983 if (texturesurfacelist[j] != surface2)
10985 Con_Printf(" %i", j - i);
10988 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
10990 for (i = 0;i < texturenumsurfaces;i = j)
10992 surface = texturesurfacelist[i];
10993 RSurf_BindLightmapForSurface(surface);
10994 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10995 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
10998 Con_Printf(" %i", j - i);
11000 surface2 = texturesurfacelist[j-1];
11001 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
11002 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
11003 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
11011 for (i = 0;i < texturenumsurfaces;i++)
11013 surface = texturesurfacelist[i];
11014 RSurf_BindLightmapForSurface(surface);
11015 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);
11020 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11023 int texturesurfaceindex;
11024 if (r_showsurfaces.integer == 2)
11026 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11028 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11029 for (j = 0;j < surface->num_triangles;j++)
11031 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
11032 GL_Color(f, f, f, 1);
11033 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
11039 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11041 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11042 int k = (int)(((size_t)surface) / sizeof(msurface_t));
11043 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);
11044 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);
11049 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11051 int texturesurfaceindex;
11055 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11057 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11058 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)
11066 rsurface.lightmapcolor4f = rsurface.array_color4f;
11067 rsurface.lightmapcolor4f_bufferobject = 0;
11068 rsurface.lightmapcolor4f_bufferoffset = 0;
11071 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11073 int texturesurfaceindex;
11079 if (rsurface.lightmapcolor4f)
11081 // generate color arrays for the surfaces in this list
11082 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11084 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11085 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)
11087 f = RSurf_FogVertex(v);
11097 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11099 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11100 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)
11102 f = RSurf_FogVertex(v);
11110 rsurface.lightmapcolor4f = rsurface.array_color4f;
11111 rsurface.lightmapcolor4f_bufferobject = 0;
11112 rsurface.lightmapcolor4f_bufferoffset = 0;
11115 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11117 int texturesurfaceindex;
11123 if (!rsurface.lightmapcolor4f)
11125 // generate color arrays for the surfaces in this list
11126 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11128 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11129 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)
11131 f = RSurf_FogVertex(v);
11132 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
11133 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
11134 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
11138 rsurface.lightmapcolor4f = rsurface.array_color4f;
11139 rsurface.lightmapcolor4f_bufferobject = 0;
11140 rsurface.lightmapcolor4f_bufferoffset = 0;
11143 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
11145 int texturesurfaceindex;
11149 if (!rsurface.lightmapcolor4f)
11151 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11153 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11154 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)
11162 rsurface.lightmapcolor4f = rsurface.array_color4f;
11163 rsurface.lightmapcolor4f_bufferobject = 0;
11164 rsurface.lightmapcolor4f_bufferoffset = 0;
11167 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11169 int texturesurfaceindex;
11173 if (!rsurface.lightmapcolor4f)
11175 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11177 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11178 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)
11180 c2[0] = c[0] + r_refdef.scene.ambient;
11181 c2[1] = c[1] + r_refdef.scene.ambient;
11182 c2[2] = c[2] + r_refdef.scene.ambient;
11186 rsurface.lightmapcolor4f = rsurface.array_color4f;
11187 rsurface.lightmapcolor4f_bufferobject = 0;
11188 rsurface.lightmapcolor4f_bufferoffset = 0;
11191 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11194 rsurface.lightmapcolor4f = NULL;
11195 rsurface.lightmapcolor4f_bufferobject = 0;
11196 rsurface.lightmapcolor4f_bufferoffset = 0;
11197 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
11198 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
11199 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
11200 GL_Color(r, g, b, a);
11201 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
11204 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11206 // TODO: optimize applyfog && applycolor case
11207 // just apply fog if necessary, and tint the fog color array if necessary
11208 rsurface.lightmapcolor4f = NULL;
11209 rsurface.lightmapcolor4f_bufferobject = 0;
11210 rsurface.lightmapcolor4f_bufferoffset = 0;
11211 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
11212 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
11213 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
11214 GL_Color(r, g, b, a);
11215 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11218 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11220 int texturesurfaceindex;
11224 if (texturesurfacelist[0]->lightmapinfo)
11226 // generate color arrays for the surfaces in this list
11227 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11229 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11230 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
11232 if (surface->lightmapinfo->samples)
11234 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
11235 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
11236 VectorScale(lm, scale, c);
11237 if (surface->lightmapinfo->styles[1] != 255)
11239 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11241 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
11242 VectorMA(c, scale, lm, c);
11243 if (surface->lightmapinfo->styles[2] != 255)
11246 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
11247 VectorMA(c, scale, lm, c);
11248 if (surface->lightmapinfo->styles[3] != 255)
11251 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
11252 VectorMA(c, scale, lm, c);
11262 rsurface.lightmapcolor4f = rsurface.array_color4f;
11263 rsurface.lightmapcolor4f_bufferobject = 0;
11264 rsurface.lightmapcolor4f_bufferoffset = 0;
11268 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
11269 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
11270 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11272 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
11273 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
11274 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
11275 GL_Color(r, g, b, a);
11276 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11279 static void RSurf_DrawBatch_GL11_ApplyFakeLight(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11281 int texturesurfaceindex;
11290 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11292 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11293 int numverts = surface->num_vertices;
11294 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
11295 n = rsurface.normal3f + 3 * surface->num_firstvertex;
11296 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
11297 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
11299 f = -DotProduct(r_refdef.view.forward, n);
11301 f = f * 0.85 + 0.15; // work around so stuff won't get black
11302 f *= r_refdef.lightmapintensity;
11303 Vector4Set(c, f, f, f, 1);
11307 rsurface.lightmapcolor4f = rsurface.array_color4f;
11308 rsurface.lightmapcolor4f_bufferobject = 0;
11309 rsurface.lightmapcolor4f_bufferoffset = 0;
11312 static void RSurf_DrawBatch_GL11_FakeLight(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11314 RSurf_DrawBatch_GL11_ApplyFakeLight(texturenumsurfaces, texturesurfacelist);
11315 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
11316 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
11317 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
11318 GL_Color(r, g, b, a);
11319 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11322 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
11324 int texturesurfaceindex;
11331 vec3_t ambientcolor;
11332 vec3_t diffusecolor;
11336 VectorCopy(rsurface.modellight_lightdir, lightdir);
11337 f = 0.5f * r_refdef.lightmapintensity;
11338 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
11339 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
11340 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
11341 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
11342 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
11343 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
11345 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
11347 // generate color arrays for the surfaces in this list
11348 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11350 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11351 int numverts = surface->num_vertices;
11352 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
11353 n = rsurface.normal3f + 3 * surface->num_firstvertex;
11354 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
11355 // q3-style directional shading
11356 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
11358 if ((f = DotProduct(n, lightdir)) > 0)
11359 VectorMA(ambientcolor, f, diffusecolor, c);
11361 VectorCopy(ambientcolor, c);
11369 rsurface.lightmapcolor4f = rsurface.array_color4f;
11370 rsurface.lightmapcolor4f_bufferobject = 0;
11371 rsurface.lightmapcolor4f_bufferoffset = 0;
11372 *applycolor = false;
11376 *r = ambientcolor[0];
11377 *g = ambientcolor[1];
11378 *b = ambientcolor[2];
11379 rsurface.lightmapcolor4f = NULL;
11380 rsurface.lightmapcolor4f_bufferobject = 0;
11381 rsurface.lightmapcolor4f_bufferoffset = 0;
11385 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11387 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
11388 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
11389 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
11390 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
11391 GL_Color(r, g, b, a);
11392 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11395 void RSurf_SetupDepthAndCulling(void)
11397 // submodels are biased to avoid z-fighting with world surfaces that they
11398 // may be exactly overlapping (avoids z-fighting artifacts on certain
11399 // doors and things in Quake maps)
11400 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
11401 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
11402 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
11403 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11406 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11408 // transparent sky would be ridiculous
11409 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11411 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11412 skyrenderlater = true;
11413 RSurf_SetupDepthAndCulling();
11414 GL_DepthMask(true);
11415 // LordHavoc: HalfLife maps have freaky skypolys so don't use
11416 // skymasking on them, and Quake3 never did sky masking (unlike
11417 // software Quake and software Quake2), so disable the sky masking
11418 // in Quake3 maps as it causes problems with q3map2 sky tricks,
11419 // and skymasking also looks very bad when noclipping outside the
11420 // level, so don't use it then either.
11421 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
11423 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
11424 R_Mesh_ColorPointer(NULL, 0, 0);
11425 R_Mesh_ResetTextureState();
11426 if (skyrendermasked)
11428 R_SetupShader_DepthOrShadow();
11429 // depth-only (masking)
11430 GL_ColorMask(0,0,0,0);
11431 // just to make sure that braindead drivers don't draw
11432 // anything despite that colormask...
11433 GL_BlendFunc(GL_ZERO, GL_ONE);
11437 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11439 GL_BlendFunc(GL_ONE, GL_ZERO);
11441 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11442 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11443 if (skyrendermasked)
11444 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11446 R_Mesh_ResetTextureState();
11447 GL_Color(1, 1, 1, 1);
11450 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
11451 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
11452 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11454 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
11456 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
11459 // render screenspace normalmap to texture
11460 GL_DepthMask(true);
11461 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY);
11462 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11464 else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
11466 // render water or distortion background, then blend surface on top
11467 GL_DepthMask(true);
11468 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
11469 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
11470 GL_DepthMask(false);
11471 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
11472 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
11473 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
11475 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11479 // render surface normally
11480 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
11481 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
11482 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
11483 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
11484 else if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
11485 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
11487 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11491 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11493 // OpenGL 1.3 path - anything not completely ancient
11494 int texturesurfaceindex;
11495 qboolean applycolor;
11498 const texturelayer_t *layer;
11499 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
11501 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
11504 int layertexrgbscale;
11505 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11507 if (layerindex == 0)
11508 GL_AlphaTest(true);
11511 GL_AlphaTest(false);
11512 qglDepthFunc(GL_EQUAL);CHECKGLERROR
11515 GL_DepthMask(layer->depthmask && writedepth);
11516 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
11517 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
11519 layertexrgbscale = 4;
11520 VectorScale(layer->color, 0.25f, layercolor);
11522 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
11524 layertexrgbscale = 2;
11525 VectorScale(layer->color, 0.5f, layercolor);
11529 layertexrgbscale = 1;
11530 VectorScale(layer->color, 1.0f, layercolor);
11532 layercolor[3] = layer->color[3];
11533 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
11534 R_Mesh_ColorPointer(NULL, 0, 0);
11535 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
11536 switch (layer->type)
11538 case TEXTURELAYERTYPE_LITTEXTURE:
11539 // single-pass lightmapped texture with 2x rgbscale
11540 R_Mesh_TexBind(0, r_texture_white);
11541 R_Mesh_TexMatrix(0, NULL);
11542 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11543 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
11544 R_Mesh_TexBind(1, layer->texture);
11545 R_Mesh_TexMatrix(1, &layer->texmatrix);
11546 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11547 R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11548 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11549 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11550 else if (FAKELIGHT_ENABLED)
11551 RSurf_DrawBatch_GL11_FakeLight(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11552 else if (rsurface.uselightmaptexture)
11553 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11555 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11557 case TEXTURELAYERTYPE_TEXTURE:
11558 // singletexture unlit texture with transparency support
11559 R_Mesh_TexBind(0, layer->texture);
11560 R_Mesh_TexMatrix(0, &layer->texmatrix);
11561 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11562 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11563 R_Mesh_TexBind(1, 0);
11564 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
11565 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11567 case TEXTURELAYERTYPE_FOG:
11568 // singletexture fogging
11569 if (layer->texture)
11571 R_Mesh_TexBind(0, layer->texture);
11572 R_Mesh_TexMatrix(0, &layer->texmatrix);
11573 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11574 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11578 R_Mesh_TexBind(0, 0);
11579 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
11581 R_Mesh_TexBind(1, 0);
11582 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
11583 // generate a color array for the fog pass
11584 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
11585 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11591 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11592 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)
11594 f = 1 - RSurf_FogVertex(v);
11595 c[0] = layercolor[0];
11596 c[1] = layercolor[1];
11597 c[2] = layercolor[2];
11598 c[3] = f * layercolor[3];
11601 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11604 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11608 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11610 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
11611 GL_AlphaTest(false);
11615 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11617 // OpenGL 1.1 - crusty old voodoo path
11618 int texturesurfaceindex;
11621 const texturelayer_t *layer;
11622 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
11624 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
11626 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11628 if (layerindex == 0)
11629 GL_AlphaTest(true);
11632 GL_AlphaTest(false);
11633 qglDepthFunc(GL_EQUAL);CHECKGLERROR
11636 GL_DepthMask(layer->depthmask && writedepth);
11637 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
11638 R_Mesh_ColorPointer(NULL, 0, 0);
11639 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
11640 switch (layer->type)
11642 case TEXTURELAYERTYPE_LITTEXTURE:
11643 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
11645 // two-pass lit texture with 2x rgbscale
11646 // first the lightmap pass
11647 R_Mesh_TexBind(0, r_texture_white);
11648 R_Mesh_TexMatrix(0, NULL);
11649 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11650 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
11651 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11652 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
11653 else if (FAKELIGHT_ENABLED)
11654 RSurf_DrawBatch_GL11_FakeLight(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
11655 else if (rsurface.uselightmaptexture)
11656 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
11658 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
11659 // then apply the texture to it
11660 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
11661 R_Mesh_TexBind(0, layer->texture);
11662 R_Mesh_TexMatrix(0, &layer->texmatrix);
11663 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11664 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11665 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);
11669 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
11670 R_Mesh_TexBind(0, layer->texture);
11671 R_Mesh_TexMatrix(0, &layer->texmatrix);
11672 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11673 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11674 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11675 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);
11677 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);
11680 case TEXTURELAYERTYPE_TEXTURE:
11681 // singletexture unlit texture with transparency support
11682 R_Mesh_TexBind(0, layer->texture);
11683 R_Mesh_TexMatrix(0, &layer->texmatrix);
11684 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11685 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11686 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);
11688 case TEXTURELAYERTYPE_FOG:
11689 // singletexture fogging
11690 if (layer->texture)
11692 R_Mesh_TexBind(0, layer->texture);
11693 R_Mesh_TexMatrix(0, &layer->texmatrix);
11694 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11695 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11699 R_Mesh_TexBind(0, 0);
11700 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
11702 // generate a color array for the fog pass
11703 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
11704 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11710 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11711 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)
11713 f = 1 - RSurf_FogVertex(v);
11714 c[0] = layer->color[0];
11715 c[1] = layer->color[1];
11716 c[2] = layer->color[2];
11717 c[3] = f * layer->color[3];
11720 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11723 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11727 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11729 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
11730 GL_AlphaTest(false);
11734 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11738 GL_AlphaTest(false);
11739 R_Mesh_ColorPointer(NULL, 0, 0);
11740 R_Mesh_ResetTextureState();
11741 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11743 if(rsurface.texture && rsurface.texture->currentskinframe)
11745 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11746 c[3] *= rsurface.texture->currentalpha;
11756 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11758 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11759 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11760 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11763 // brighten it up (as texture value 127 means "unlit")
11764 c[0] *= 2 * r_refdef.view.colorscale;
11765 c[1] *= 2 * r_refdef.view.colorscale;
11766 c[2] *= 2 * r_refdef.view.colorscale;
11768 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11769 c[3] *= r_wateralpha.value;
11771 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11773 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11774 GL_DepthMask(false);
11776 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11778 GL_BlendFunc(GL_ONE, GL_ONE);
11779 GL_DepthMask(false);
11781 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11783 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11784 GL_DepthMask(false);
11786 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11788 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11789 GL_DepthMask(false);
11793 GL_BlendFunc(GL_ONE, GL_ZERO);
11794 GL_DepthMask(writedepth);
11797 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11799 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11801 rsurface.lightmapcolor4f = NULL;
11802 rsurface.lightmapcolor4f_bufferobject = 0;
11803 rsurface.lightmapcolor4f_bufferoffset = 0;
11805 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11807 qboolean applycolor = true;
11810 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
11812 r_refdef.lightmapintensity = 1;
11813 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
11814 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11816 else if (FAKELIGHT_ENABLED)
11818 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
11820 r_refdef.lightmapintensity = r_fakelight_intensity.value;
11821 RSurf_DrawBatch_GL11_ApplyFakeLight(texturenumsurfaces, texturesurfacelist);
11822 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11826 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11828 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
11829 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
11830 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11833 if(!rsurface.lightmapcolor4f)
11834 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
11836 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
11837 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
11838 if(r_refdef.fogenabled)
11839 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
11841 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
11842 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11845 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11848 RSurf_SetupDepthAndCulling();
11849 if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
11851 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11854 switch (vid.renderpath)
11856 case RENDERPATH_GL20:
11857 case RENDERPATH_CGGL:
11858 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11860 case RENDERPATH_GL13:
11861 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11863 case RENDERPATH_GL11:
11864 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11870 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11873 RSurf_SetupDepthAndCulling();
11874 if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
11876 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11879 switch (vid.renderpath)
11881 case RENDERPATH_GL20:
11882 case RENDERPATH_CGGL:
11883 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11885 case RENDERPATH_GL13:
11886 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11888 case RENDERPATH_GL11:
11889 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11895 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11898 int texturenumsurfaces, endsurface;
11899 texture_t *texture;
11900 const msurface_t *surface;
11901 #define MAXBATCH_TRANSPARENTSURFACES 256
11902 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
11904 // if the model is static it doesn't matter what value we give for
11905 // wantnormals and wanttangents, so this logic uses only rules applicable
11906 // to a model, knowing that they are meaningless otherwise
11907 if (ent == r_refdef.scene.worldentity)
11908 RSurf_ActiveWorldEntity();
11909 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11910 RSurf_ActiveModelEntity(ent, false, false, false);
11913 switch (vid.renderpath)
11915 case RENDERPATH_GL20:
11916 case RENDERPATH_CGGL:
11917 RSurf_ActiveModelEntity(ent, true, true, false);
11919 case RENDERPATH_GL13:
11920 case RENDERPATH_GL11:
11921 RSurf_ActiveModelEntity(ent, true, false, false);
11926 if (r_transparentdepthmasking.integer)
11928 qboolean setup = false;
11929 for (i = 0;i < numsurfaces;i = j)
11932 surface = rsurface.modelsurfaces + surfacelist[i];
11933 texture = surface->texture;
11934 rsurface.texture = R_GetCurrentTexture(texture);
11935 // scan ahead until we find a different texture
11936 endsurface = min(i + 1024, numsurfaces);
11937 texturenumsurfaces = 0;
11938 texturesurfacelist[texturenumsurfaces++] = surface;
11939 if(FAKELIGHT_ENABLED)
11941 rsurface.uselightmaptexture = false;
11942 for (;j < endsurface;j++)
11944 surface = rsurface.modelsurfaces + surfacelist[j];
11945 if (texture != surface->texture)
11947 texturesurfacelist[texturenumsurfaces++] = surface;
11952 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11953 for (;j < endsurface;j++)
11955 surface = rsurface.modelsurfaces + surfacelist[j];
11956 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
11958 texturesurfacelist[texturenumsurfaces++] = surface;
11961 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11963 // render the range of surfaces as depth
11967 GL_ColorMask(0,0,0,0);
11969 GL_DepthTest(true);
11970 GL_BlendFunc(GL_ONE, GL_ZERO);
11971 GL_DepthMask(true);
11972 GL_AlphaTest(false);
11973 R_Mesh_ColorPointer(NULL, 0, 0);
11974 R_Mesh_ResetTextureState();
11975 R_SetupShader_DepthOrShadow();
11977 RSurf_SetupDepthAndCulling();
11978 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11979 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11982 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11985 for (i = 0;i < numsurfaces;i = j)
11988 surface = rsurface.modelsurfaces + surfacelist[i];
11989 texture = surface->texture;
11990 rsurface.texture = R_GetCurrentTexture(texture);
11991 // scan ahead until we find a different texture
11992 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
11993 texturenumsurfaces = 0;
11994 texturesurfacelist[texturenumsurfaces++] = surface;
11995 if(FAKELIGHT_ENABLED)
11997 rsurface.uselightmaptexture = false;
11998 for (;j < endsurface;j++)
12000 surface = rsurface.modelsurfaces + surfacelist[j];
12001 if (texture != surface->texture)
12003 texturesurfacelist[texturenumsurfaces++] = surface;
12008 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
12009 for (;j < endsurface;j++)
12011 surface = rsurface.modelsurfaces + surfacelist[j];
12012 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
12014 texturesurfacelist[texturenumsurfaces++] = surface;
12017 // render the range of surfaces
12018 if (ent == r_refdef.scene.worldentity)
12019 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12021 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12023 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12024 GL_AlphaTest(false);
12027 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
12029 // transparent surfaces get pushed off into the transparent queue
12030 int surfacelistindex;
12031 const msurface_t *surface;
12032 vec3_t tempcenter, center;
12033 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
12035 surface = texturesurfacelist[surfacelistindex];
12036 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
12037 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
12038 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
12039 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
12040 if (queueentity->transparent_offset) // transparent offset
12042 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
12043 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
12044 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
12046 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
12050 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
12052 const entity_render_t *queueentity = r_refdef.scene.worldentity;
12056 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
12058 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
12060 RSurf_SetupDepthAndCulling();
12061 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
12062 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
12066 if (!rsurface.texture->currentnumlayers)
12068 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12069 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12071 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12073 else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
12075 RSurf_SetupDepthAndCulling();
12076 GL_AlphaTest(false);
12077 R_Mesh_ColorPointer(NULL, 0, 0);
12078 R_Mesh_ResetTextureState();
12079 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12080 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
12081 GL_DepthMask(true);
12082 GL_BlendFunc(GL_ONE, GL_ZERO);
12083 GL_Color(0, 0, 0, 1);
12084 GL_DepthTest(writedepth);
12085 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
12087 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
12089 RSurf_SetupDepthAndCulling();
12090 GL_AlphaTest(false);
12091 R_Mesh_ColorPointer(NULL, 0, 0);
12092 R_Mesh_ResetTextureState();
12093 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12094 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
12095 GL_DepthMask(true);
12096 GL_BlendFunc(GL_ONE, GL_ZERO);
12097 GL_DepthTest(true);
12098 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
12100 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
12101 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12102 else if (!rsurface.texture->currentnumlayers)
12104 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12106 // in the deferred case, transparent surfaces were queued during prepass
12107 if (!r_shadow_usingdeferredprepass)
12108 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12112 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12113 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12118 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12121 texture_t *texture;
12122 // break the surface list down into batches by texture and use of lightmapping
12123 for (i = 0;i < numsurfaces;i = j)
12126 // texture is the base texture pointer, rsurface.texture is the
12127 // current frame/skin the texture is directing us to use (for example
12128 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12129 // use skin 1 instead)
12130 texture = surfacelist[i]->texture;
12131 rsurface.texture = R_GetCurrentTexture(texture);
12132 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12134 // if this texture is not the kind we want, skip ahead to the next one
12135 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12139 if(FAKELIGHT_ENABLED || depthonly || prepass)
12141 rsurface.uselightmaptexture = false;
12142 // simply scan ahead until we find a different texture or lightmap state
12143 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12148 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
12149 // simply scan ahead until we find a different texture or lightmap state
12150 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
12153 // render the range of surfaces
12154 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
12158 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
12163 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
12165 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
12167 RSurf_SetupDepthAndCulling();
12168 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
12169 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
12173 if (!rsurface.texture->currentnumlayers)
12175 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12176 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12178 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12180 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
12182 RSurf_SetupDepthAndCulling();
12183 GL_AlphaTest(false);
12184 R_Mesh_ColorPointer(NULL, 0, 0);
12185 R_Mesh_ResetTextureState();
12186 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12187 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
12188 GL_DepthMask(true);
12189 GL_BlendFunc(GL_ONE, GL_ZERO);
12190 GL_Color(0, 0, 0, 1);
12191 GL_DepthTest(writedepth);
12192 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
12194 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12196 RSurf_SetupDepthAndCulling();
12197 GL_AlphaTest(false);
12198 R_Mesh_ColorPointer(NULL, 0, 0);
12199 R_Mesh_ResetTextureState();
12200 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12201 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
12202 GL_DepthMask(true);
12203 GL_BlendFunc(GL_ONE, GL_ZERO);
12204 GL_DepthTest(true);
12205 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
12207 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
12208 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12209 else if (!rsurface.texture->currentnumlayers)
12211 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12213 // in the deferred case, transparent surfaces were queued during prepass
12214 if (!r_shadow_usingdeferredprepass)
12215 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12219 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12220 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12225 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12228 texture_t *texture;
12229 // break the surface list down into batches by texture and use of lightmapping
12230 for (i = 0;i < numsurfaces;i = j)
12233 // texture is the base texture pointer, rsurface.texture is the
12234 // current frame/skin the texture is directing us to use (for example
12235 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12236 // use skin 1 instead)
12237 texture = surfacelist[i]->texture;
12238 rsurface.texture = R_GetCurrentTexture(texture);
12239 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12241 // if this texture is not the kind we want, skip ahead to the next one
12242 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12246 if(FAKELIGHT_ENABLED || depthonly || prepass)
12248 rsurface.uselightmaptexture = false;
12249 // simply scan ahead until we find a different texture or lightmap state
12250 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12255 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
12256 // simply scan ahead until we find a different texture or lightmap state
12257 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
12260 // render the range of surfaces
12261 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
12265 float locboxvertex3f[6*4*3] =
12267 1,0,1, 1,0,0, 1,1,0, 1,1,1,
12268 0,1,1, 0,1,0, 0,0,0, 0,0,1,
12269 1,1,1, 1,1,0, 0,1,0, 0,1,1,
12270 0,0,1, 0,0,0, 1,0,0, 1,0,1,
12271 0,0,1, 1,0,1, 1,1,1, 0,1,1,
12272 1,0,0, 0,0,0, 0,1,0, 1,1,0
12275 unsigned short locboxelements[6*2*3] =
12280 12,13,14, 12,14,15,
12281 16,17,18, 16,18,19,
12285 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12288 cl_locnode_t *loc = (cl_locnode_t *)ent;
12290 float vertex3f[6*4*3];
12292 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12293 GL_DepthMask(false);
12294 GL_DepthRange(0, 1);
12295 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12296 GL_DepthTest(true);
12297 GL_CullFace(GL_NONE);
12298 R_EntityMatrix(&identitymatrix);
12300 R_Mesh_VertexPointer(vertex3f, 0, 0);
12301 R_Mesh_ColorPointer(NULL, 0, 0);
12302 R_Mesh_ResetTextureState();
12303 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12305 i = surfacelist[0];
12306 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12307 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12308 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12309 surfacelist[0] < 0 ? 0.5f : 0.125f);
12311 if (VectorCompare(loc->mins, loc->maxs))
12313 VectorSet(size, 2, 2, 2);
12314 VectorMA(loc->mins, -0.5f, size, mins);
12318 VectorCopy(loc->mins, mins);
12319 VectorSubtract(loc->maxs, loc->mins, size);
12322 for (i = 0;i < 6*4*3;)
12323 for (j = 0;j < 3;j++, i++)
12324 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
12326 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
12329 void R_DrawLocs(void)
12332 cl_locnode_t *loc, *nearestloc;
12334 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
12335 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
12337 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
12338 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
12342 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
12344 if (decalsystem->decals)
12345 Mem_Free(decalsystem->decals);
12346 memset(decalsystem, 0, sizeof(*decalsystem));
12349 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)
12352 tridecal_t *decals;
12355 // expand or initialize the system
12356 if (decalsystem->maxdecals <= decalsystem->numdecals)
12358 decalsystem_t old = *decalsystem;
12359 qboolean useshortelements;
12360 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
12361 useshortelements = decalsystem->maxdecals * 3 <= 65536;
12362 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)));
12363 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
12364 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
12365 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
12366 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
12367 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
12368 if (decalsystem->numdecals)
12369 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
12371 Mem_Free(old.decals);
12372 for (i = 0;i < decalsystem->maxdecals*3;i++)
12373 decalsystem->element3i[i] = i;
12374 if (useshortelements)
12375 for (i = 0;i < decalsystem->maxdecals*3;i++)
12376 decalsystem->element3s[i] = i;
12379 // grab a decal and search for another free slot for the next one
12380 decals = decalsystem->decals;
12381 decal = decalsystem->decals + (i = decalsystem->freedecal++);
12382 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
12384 decalsystem->freedecal = i;
12385 if (decalsystem->numdecals <= i)
12386 decalsystem->numdecals = i + 1;
12388 // initialize the decal
12390 decal->triangleindex = triangleindex;
12391 decal->surfaceindex = surfaceindex;
12392 decal->decalsequence = decalsequence;
12393 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
12394 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
12395 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
12396 decal->color4ub[0][3] = 255;
12397 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
12398 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
12399 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
12400 decal->color4ub[1][3] = 255;
12401 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
12402 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
12403 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
12404 decal->color4ub[2][3] = 255;
12405 decal->vertex3f[0][0] = v0[0];
12406 decal->vertex3f[0][1] = v0[1];
12407 decal->vertex3f[0][2] = v0[2];
12408 decal->vertex3f[1][0] = v1[0];
12409 decal->vertex3f[1][1] = v1[1];
12410 decal->vertex3f[1][2] = v1[2];
12411 decal->vertex3f[2][0] = v2[0];
12412 decal->vertex3f[2][1] = v2[1];
12413 decal->vertex3f[2][2] = v2[2];
12414 decal->texcoord2f[0][0] = t0[0];
12415 decal->texcoord2f[0][1] = t0[1];
12416 decal->texcoord2f[1][0] = t1[0];
12417 decal->texcoord2f[1][1] = t1[1];
12418 decal->texcoord2f[2][0] = t2[0];
12419 decal->texcoord2f[2][1] = t2[1];
12422 extern cvar_t cl_decals_bias;
12423 extern cvar_t cl_decals_models;
12424 extern cvar_t cl_decals_newsystem_intensitymultiplier;
12425 // baseparms, parms, temps
12426 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)
12431 const float *vertex3f;
12433 float points[2][9][3];
12440 e = rsurface.modelelement3i + 3*triangleindex;
12442 vertex3f = rsurface.modelvertex3f;
12444 for (cornerindex = 0;cornerindex < 3;cornerindex++)
12446 index = 3*e[cornerindex];
12447 VectorCopy(vertex3f + index, v[cornerindex]);
12450 //TriangleNormal(v[0], v[1], v[2], normal);
12451 //if (DotProduct(normal, localnormal) < 0.0f)
12453 // clip by each of the box planes formed from the projection matrix
12454 // if anything survives, we emit the decal
12455 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]);
12458 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]);
12461 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]);
12464 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]);
12467 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]);
12470 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]);
12473 // some part of the triangle survived, so we have to accept it...
12476 // dynamic always uses the original triangle
12478 for (cornerindex = 0;cornerindex < 3;cornerindex++)
12480 index = 3*e[cornerindex];
12481 VectorCopy(vertex3f + index, v[cornerindex]);
12484 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
12486 // convert vertex positions to texcoords
12487 Matrix4x4_Transform(projection, v[cornerindex], temp);
12488 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
12489 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
12490 // calculate distance fade from the projection origin
12491 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
12492 f = bound(0.0f, f, 1.0f);
12493 c[cornerindex][0] = r * f;
12494 c[cornerindex][1] = g * f;
12495 c[cornerindex][2] = b * f;
12496 c[cornerindex][3] = 1.0f;
12497 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
12500 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);
12502 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
12503 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);
12505 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)
12507 matrix4x4_t projection;
12508 decalsystem_t *decalsystem;
12511 const msurface_t *surface;
12512 const msurface_t *surfaces;
12513 const int *surfacelist;
12514 const texture_t *texture;
12516 int numsurfacelist;
12517 int surfacelistindex;
12520 float localorigin[3];
12521 float localnormal[3];
12522 float localmins[3];
12523 float localmaxs[3];
12526 float planes[6][4];
12529 int bih_triangles_count;
12530 int bih_triangles[256];
12531 int bih_surfaces[256];
12533 decalsystem = &ent->decalsystem;
12534 model = ent->model;
12535 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
12537 R_DecalSystem_Reset(&ent->decalsystem);
12541 if (!model->brush.data_nodes && !cl_decals_models.integer)
12543 if (decalsystem->model)
12544 R_DecalSystem_Reset(decalsystem);
12548 if (decalsystem->model != model)
12549 R_DecalSystem_Reset(decalsystem);
12550 decalsystem->model = model;
12552 RSurf_ActiveModelEntity(ent, false, false, false);
12554 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
12555 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
12556 VectorNormalize(localnormal);
12557 localsize = worldsize*rsurface.inversematrixscale;
12558 localmins[0] = localorigin[0] - localsize;
12559 localmins[1] = localorigin[1] - localsize;
12560 localmins[2] = localorigin[2] - localsize;
12561 localmaxs[0] = localorigin[0] + localsize;
12562 localmaxs[1] = localorigin[1] + localsize;
12563 localmaxs[2] = localorigin[2] + localsize;
12565 //VectorCopy(localnormal, planes[4]);
12566 //VectorVectors(planes[4], planes[2], planes[0]);
12567 AnglesFromVectors(angles, localnormal, NULL, false);
12568 AngleVectors(angles, planes[0], planes[2], planes[4]);
12569 VectorNegate(planes[0], planes[1]);
12570 VectorNegate(planes[2], planes[3]);
12571 VectorNegate(planes[4], planes[5]);
12572 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
12573 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
12574 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
12575 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
12576 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
12577 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
12582 matrix4x4_t forwardprojection;
12583 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
12584 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
12589 float projectionvector[4][3];
12590 VectorScale(planes[0], ilocalsize, projectionvector[0]);
12591 VectorScale(planes[2], ilocalsize, projectionvector[1]);
12592 VectorScale(planes[4], ilocalsize, projectionvector[2]);
12593 projectionvector[0][0] = planes[0][0] * ilocalsize;
12594 projectionvector[0][1] = planes[1][0] * ilocalsize;
12595 projectionvector[0][2] = planes[2][0] * ilocalsize;
12596 projectionvector[1][0] = planes[0][1] * ilocalsize;
12597 projectionvector[1][1] = planes[1][1] * ilocalsize;
12598 projectionvector[1][2] = planes[2][1] * ilocalsize;
12599 projectionvector[2][0] = planes[0][2] * ilocalsize;
12600 projectionvector[2][1] = planes[1][2] * ilocalsize;
12601 projectionvector[2][2] = planes[2][2] * ilocalsize;
12602 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
12603 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
12604 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
12605 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
12609 dynamic = model->surfmesh.isanimated;
12610 numsurfacelist = model->nummodelsurfaces;
12611 surfacelist = model->sortedmodelsurfaces;
12612 surfaces = model->data_surfaces;
12615 bih_triangles_count = -1;
12618 if(model->render_bih.numleafs)
12619 bih = &model->render_bih;
12620 else if(model->collision_bih.numleafs)
12621 bih = &model->collision_bih;
12624 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
12625 if(bih_triangles_count == 0)
12627 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
12629 if(bih_triangles_count > 0)
12631 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
12633 surfaceindex = bih_surfaces[triangleindex];
12634 surface = surfaces + surfaceindex;
12635 texture = surface->texture;
12636 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12638 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12640 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
12645 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
12647 surfaceindex = surfacelist[surfacelistindex];
12648 surface = surfaces + surfaceindex;
12649 // check cull box first because it rejects more than any other check
12650 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
12652 // skip transparent surfaces
12653 texture = surface->texture;
12654 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12656 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12658 numtriangles = surface->num_triangles;
12659 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
12660 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
12665 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
12666 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)
12668 int renderentityindex;
12669 float worldmins[3];
12670 float worldmaxs[3];
12671 entity_render_t *ent;
12673 if (!cl_decals_newsystem.integer)
12676 worldmins[0] = worldorigin[0] - worldsize;
12677 worldmins[1] = worldorigin[1] - worldsize;
12678 worldmins[2] = worldorigin[2] - worldsize;
12679 worldmaxs[0] = worldorigin[0] + worldsize;
12680 worldmaxs[1] = worldorigin[1] + worldsize;
12681 worldmaxs[2] = worldorigin[2] + worldsize;
12683 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12685 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
12687 ent = r_refdef.scene.entities[renderentityindex];
12688 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
12691 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12695 typedef struct r_decalsystem_splatqueue_s
12697 vec3_t worldorigin;
12698 vec3_t worldnormal;
12704 r_decalsystem_splatqueue_t;
12706 int r_decalsystem_numqueued = 0;
12707 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12709 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)
12711 r_decalsystem_splatqueue_t *queue;
12713 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12716 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12717 VectorCopy(worldorigin, queue->worldorigin);
12718 VectorCopy(worldnormal, queue->worldnormal);
12719 Vector4Set(queue->color, r, g, b, a);
12720 Vector4Set(queue->tcrange, s1, t1, s2, t2);
12721 queue->worldsize = worldsize;
12722 queue->decalsequence = cl.decalsequence++;
12725 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12728 r_decalsystem_splatqueue_t *queue;
12730 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12731 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);
12732 r_decalsystem_numqueued = 0;
12735 extern cvar_t cl_decals_max;
12736 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12739 decalsystem_t *decalsystem = &ent->decalsystem;
12746 if (!decalsystem->numdecals)
12749 if (r_showsurfaces.integer)
12752 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12754 R_DecalSystem_Reset(decalsystem);
12758 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
12759 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12761 if (decalsystem->lastupdatetime)
12762 frametime = (cl.time - decalsystem->lastupdatetime);
12765 decalsystem->lastupdatetime = cl.time;
12766 decal = decalsystem->decals;
12767 numdecals = decalsystem->numdecals;
12769 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12771 if (decal->color4ub[0][3])
12773 decal->lived += frametime;
12774 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
12776 memset(decal, 0, sizeof(*decal));
12777 if (decalsystem->freedecal > i)
12778 decalsystem->freedecal = i;
12782 decal = decalsystem->decals;
12783 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
12786 // collapse the array by shuffling the tail decals into the gaps
12789 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
12790 decalsystem->freedecal++;
12791 if (decalsystem->freedecal == numdecals)
12793 decal[decalsystem->freedecal] = decal[--numdecals];
12796 decalsystem->numdecals = numdecals;
12798 if (numdecals <= 0)
12800 // if there are no decals left, reset decalsystem
12801 R_DecalSystem_Reset(decalsystem);
12805 extern skinframe_t *decalskinframe;
12806 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12809 decalsystem_t *decalsystem = &ent->decalsystem;
12818 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12821 numdecals = decalsystem->numdecals;
12825 if (r_showsurfaces.integer)
12828 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12830 R_DecalSystem_Reset(decalsystem);
12834 // if the model is static it doesn't matter what value we give for
12835 // wantnormals and wanttangents, so this logic uses only rules applicable
12836 // to a model, knowing that they are meaningless otherwise
12837 if (ent == r_refdef.scene.worldentity)
12838 RSurf_ActiveWorldEntity();
12840 RSurf_ActiveModelEntity(ent, false, false, false);
12842 decalsystem->lastupdatetime = cl.time;
12843 decal = decalsystem->decals;
12845 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12847 // update vertex positions for animated models
12848 v3f = decalsystem->vertex3f;
12849 c4f = decalsystem->color4f;
12850 t2f = decalsystem->texcoord2f;
12851 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12853 if (!decal->color4ub[0][3])
12856 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12859 // update color values for fading decals
12860 if (decal->lived >= cl_decals_time.value)
12862 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12863 alpha *= (1.0f/255.0f);
12866 alpha = 1.0f/255.0f;
12868 c4f[ 0] = decal->color4ub[0][0] * alpha;
12869 c4f[ 1] = decal->color4ub[0][1] * alpha;
12870 c4f[ 2] = decal->color4ub[0][2] * alpha;
12872 c4f[ 4] = decal->color4ub[1][0] * alpha;
12873 c4f[ 5] = decal->color4ub[1][1] * alpha;
12874 c4f[ 6] = decal->color4ub[1][2] * alpha;
12876 c4f[ 8] = decal->color4ub[2][0] * alpha;
12877 c4f[ 9] = decal->color4ub[2][1] * alpha;
12878 c4f[10] = decal->color4ub[2][2] * alpha;
12881 t2f[0] = decal->texcoord2f[0][0];
12882 t2f[1] = decal->texcoord2f[0][1];
12883 t2f[2] = decal->texcoord2f[1][0];
12884 t2f[3] = decal->texcoord2f[1][1];
12885 t2f[4] = decal->texcoord2f[2][0];
12886 t2f[5] = decal->texcoord2f[2][1];
12888 // update vertex positions for animated models
12889 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
12891 e = rsurface.modelelement3i + 3*decal->triangleindex;
12892 VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
12893 VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
12894 VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
12898 VectorCopy(decal->vertex3f[0], v3f);
12899 VectorCopy(decal->vertex3f[1], v3f + 3);
12900 VectorCopy(decal->vertex3f[2], v3f + 6);
12903 if (r_refdef.fogenabled)
12905 alpha = RSurf_FogVertex(v3f);
12906 VectorScale(c4f, alpha, c4f);
12907 alpha = RSurf_FogVertex(v3f + 3);
12908 VectorScale(c4f + 4, alpha, c4f + 4);
12909 alpha = RSurf_FogVertex(v3f + 6);
12910 VectorScale(c4f + 8, alpha, c4f + 8);
12921 r_refdef.stats.drawndecals += numtris;
12923 // now render the decals all at once
12924 // (this assumes they all use one particle font texture!)
12925 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);
12926 R_Mesh_ResetTextureState();
12927 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
12928 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
12929 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
12930 GL_DepthMask(false);
12931 GL_DepthRange(0, 1);
12932 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12933 GL_DepthTest(true);
12934 GL_CullFace(GL_NONE);
12935 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12936 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
12937 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
12941 static void R_DrawModelDecals(void)
12945 // fade faster when there are too many decals
12946 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12947 for (i = 0;i < r_refdef.scene.numentities;i++)
12948 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12950 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12951 for (i = 0;i < r_refdef.scene.numentities;i++)
12952 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12953 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12955 R_DecalSystem_ApplySplatEntitiesQueue();
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_refdef.stats.totaldecals += numdecals;
12963 if (r_showsurfaces.integer)
12966 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12968 for (i = 0;i < r_refdef.scene.numentities;i++)
12970 if (!r_refdef.viewcache.entityvisible[i])
12972 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12973 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12977 extern cvar_t mod_collision_bih;
12978 void R_DrawDebugModel(void)
12980 entity_render_t *ent = rsurface.entity;
12981 int i, j, k, l, flagsmask;
12982 const msurface_t *surface;
12983 dp_model_t *model = ent->model;
12986 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12988 R_Mesh_ColorPointer(NULL, 0, 0);
12989 R_Mesh_ResetTextureState();
12990 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12991 GL_DepthRange(0, 1);
12992 GL_DepthTest(!r_showdisabledepthtest.integer);
12993 GL_DepthMask(false);
12994 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12996 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
13000 qboolean cullbox = ent == r_refdef.scene.worldentity;
13001 const q3mbrush_t *brush;
13002 const bih_t *bih = &model->collision_bih;
13003 const bih_leaf_t *bihleaf;
13004 float vertex3f[3][3];
13005 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
13007 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
13009 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
13011 switch (bihleaf->type)
13014 brush = model->brush.data_brushes + bihleaf->itemindex;
13015 if (brush->colbrushf && brush->colbrushf->numtriangles)
13017 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
13018 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);
13019 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
13022 case BIH_COLLISIONTRIANGLE:
13023 triangleindex = bihleaf->itemindex;
13024 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
13025 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
13026 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
13027 R_Mesh_VertexPointer(vertex3f[0], 0, 0);
13028 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);
13029 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, polygonelement3s, 0, 0);
13031 case BIH_RENDERTRIANGLE:
13032 triangleindex = bihleaf->itemindex;
13033 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
13034 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
13035 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
13036 R_Mesh_VertexPointer(vertex3f[0], 0, 0);
13037 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);
13038 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, polygonelement3s, 0, 0);
13044 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13046 if (r_showtris.integer || r_shownormals.integer)
13048 if (r_showdisabledepthtest.integer)
13050 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13051 GL_DepthMask(false);
13055 GL_BlendFunc(GL_ONE, GL_ZERO);
13056 GL_DepthMask(true);
13058 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
13060 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
13062 rsurface.texture = R_GetCurrentTexture(surface->texture);
13063 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
13065 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
13066 if (r_showtris.value > 0)
13068 if (!rsurface.texture->currentlayers->depthmask)
13069 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
13070 else if (ent == r_refdef.scene.worldentity)
13071 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
13073 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
13074 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
13075 R_Mesh_ColorPointer(NULL, 0, 0);
13076 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
13077 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
13078 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
13079 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);
13080 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
13083 if (r_shownormals.value < 0)
13085 qglBegin(GL_LINES);
13086 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13088 VectorCopy(rsurface.vertex3f + l * 3, v);
13089 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13090 qglVertex3f(v[0], v[1], v[2]);
13091 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
13092 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13093 qglVertex3f(v[0], v[1], v[2]);
13098 if (r_shownormals.value > 0)
13100 qglBegin(GL_LINES);
13101 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13103 VectorCopy(rsurface.vertex3f + l * 3, v);
13104 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13105 qglVertex3f(v[0], v[1], v[2]);
13106 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
13107 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13108 qglVertex3f(v[0], v[1], v[2]);
13112 qglBegin(GL_LINES);
13113 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13115 VectorCopy(rsurface.vertex3f + l * 3, v);
13116 GL_Color(0, r_refdef.view.colorscale, 0, 1);
13117 qglVertex3f(v[0], v[1], v[2]);
13118 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
13119 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13120 qglVertex3f(v[0], v[1], v[2]);
13124 qglBegin(GL_LINES);
13125 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13127 VectorCopy(rsurface.vertex3f + l * 3, v);
13128 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13129 qglVertex3f(v[0], v[1], v[2]);
13130 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
13131 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13132 qglVertex3f(v[0], v[1], v[2]);
13139 rsurface.texture = NULL;
13143 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
13144 int r_maxsurfacelist = 0;
13145 const msurface_t **r_surfacelist = NULL;
13146 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13148 int i, j, endj, flagsmask;
13149 dp_model_t *model = r_refdef.scene.worldmodel;
13150 msurface_t *surfaces;
13151 unsigned char *update;
13152 int numsurfacelist = 0;
13156 if (r_maxsurfacelist < model->num_surfaces)
13158 r_maxsurfacelist = model->num_surfaces;
13160 Mem_Free((msurface_t**)r_surfacelist);
13161 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13164 RSurf_ActiveWorldEntity();
13166 surfaces = model->data_surfaces;
13167 update = model->brushq1.lightmapupdateflags;
13169 // update light styles on this submodel
13170 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13172 model_brush_lightstyleinfo_t *style;
13173 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13175 if (style->value != r_refdef.scene.lightstylevalue[style->style])
13177 int *list = style->surfacelist;
13178 style->value = r_refdef.scene.lightstylevalue[style->style];
13179 for (j = 0;j < style->numsurfaces;j++)
13180 update[list[j]] = true;
13185 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13189 R_DrawDebugModel();
13190 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13194 rsurface.uselightmaptexture = false;
13195 rsurface.texture = NULL;
13196 rsurface.rtlight = NULL;
13197 numsurfacelist = 0;
13198 // add visible surfaces to draw list
13199 for (i = 0;i < model->nummodelsurfaces;i++)
13201 j = model->sortedmodelsurfaces[i];
13202 if (r_refdef.viewcache.world_surfacevisible[j])
13203 r_surfacelist[numsurfacelist++] = surfaces + j;
13205 // update lightmaps if needed
13206 if (model->brushq1.firstrender)
13208 model->brushq1.firstrender = false;
13209 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13211 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13215 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13216 if (r_refdef.viewcache.world_surfacevisible[j])
13218 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13220 // don't do anything if there were no surfaces
13221 if (!numsurfacelist)
13223 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13226 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13227 GL_AlphaTest(false);
13229 // add to stats if desired
13230 if (r_speeds.integer && !skysurfaces && !depthonly)
13232 r_refdef.stats.world_surfaces += numsurfacelist;
13233 for (j = 0;j < numsurfacelist;j++)
13234 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
13237 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13240 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13242 int i, j, endj, flagsmask;
13243 dp_model_t *model = ent->model;
13244 msurface_t *surfaces;
13245 unsigned char *update;
13246 int numsurfacelist = 0;
13250 if (r_maxsurfacelist < model->num_surfaces)
13252 r_maxsurfacelist = model->num_surfaces;
13254 Mem_Free((msurface_t **)r_surfacelist);
13255 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13258 // if the model is static it doesn't matter what value we give for
13259 // wantnormals and wanttangents, so this logic uses only rules applicable
13260 // to a model, knowing that they are meaningless otherwise
13261 if (ent == r_refdef.scene.worldentity)
13262 RSurf_ActiveWorldEntity();
13263 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13264 RSurf_ActiveModelEntity(ent, false, false, false);
13266 RSurf_ActiveModelEntity(ent, true, true, true);
13267 else if (depthonly)
13269 switch (vid.renderpath)
13271 case RENDERPATH_GL20:
13272 case RENDERPATH_CGGL:
13273 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
13275 case RENDERPATH_GL13:
13276 case RENDERPATH_GL11:
13277 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
13283 switch (vid.renderpath)
13285 case RENDERPATH_GL20:
13286 case RENDERPATH_CGGL:
13287 RSurf_ActiveModelEntity(ent, true, true, false);
13289 case RENDERPATH_GL13:
13290 case RENDERPATH_GL11:
13291 RSurf_ActiveModelEntity(ent, true, false, false);
13296 surfaces = model->data_surfaces;
13297 update = model->brushq1.lightmapupdateflags;
13299 // update light styles
13300 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13302 model_brush_lightstyleinfo_t *style;
13303 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13305 if (style->value != r_refdef.scene.lightstylevalue[style->style])
13307 int *list = style->surfacelist;
13308 style->value = r_refdef.scene.lightstylevalue[style->style];
13309 for (j = 0;j < style->numsurfaces;j++)
13310 update[list[j]] = true;
13315 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13319 R_DrawDebugModel();
13320 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13324 rsurface.uselightmaptexture = false;
13325 rsurface.texture = NULL;
13326 rsurface.rtlight = NULL;
13327 numsurfacelist = 0;
13328 // add visible surfaces to draw list
13329 for (i = 0;i < model->nummodelsurfaces;i++)
13330 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
13331 // don't do anything if there were no surfaces
13332 if (!numsurfacelist)
13334 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13337 // update lightmaps if needed
13341 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13346 R_BuildLightMap(ent, surfaces + j);
13351 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13353 R_BuildLightMap(ent, surfaces + j);
13354 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13355 GL_AlphaTest(false);
13357 // add to stats if desired
13358 if (r_speeds.integer && !skysurfaces && !depthonly)
13360 r_refdef.stats.entities_surfaces += numsurfacelist;
13361 for (j = 0;j < numsurfacelist;j++)
13362 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
13365 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13368 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
13370 static texture_t texture;
13371 static msurface_t surface;
13372 const msurface_t *surfacelist = &surface;
13374 // fake enough texture and surface state to render this geometry
13376 texture.update_lastrenderframe = -1; // regenerate this texture
13377 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
13378 texture.currentskinframe = skinframe;
13379 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
13380 texture.offsetmapping = OFFSETMAPPING_OFF;
13381 texture.offsetscale = 1;
13382 texture.specularscalemod = 1;
13383 texture.specularpowermod = 1;
13385 surface.texture = &texture;
13386 surface.num_triangles = numtriangles;
13387 surface.num_firsttriangle = firsttriangle;
13388 surface.num_vertices = numvertices;
13389 surface.num_firstvertex = firstvertex;
13392 rsurface.texture = R_GetCurrentTexture(surface.texture);
13393 rsurface.uselightmaptexture = false;
13394 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
13397 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)
13399 static msurface_t surface;
13400 const msurface_t *surfacelist = &surface;
13402 // fake enough texture and surface state to render this geometry
13404 surface.texture = texture;
13405 surface.num_triangles = numtriangles;
13406 surface.num_firsttriangle = firsttriangle;
13407 surface.num_vertices = numvertices;
13408 surface.num_firstvertex = firstvertex;
13411 rsurface.texture = R_GetCurrentTexture(surface.texture);
13412 rsurface.uselightmaptexture = false;
13413 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);