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"
33 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
36 mempool_t *r_main_mempool;
37 rtexturepool_t *r_main_texturepool;
39 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41 static qboolean r_loadnormalmap;
42 static qboolean r_loadgloss;
44 static qboolean r_loaddds;
45 static qboolean r_savedds;
52 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
53 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
54 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
55 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
56 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)"};
57 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
58 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
59 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
61 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
62 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"};
63 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
64 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)"};
65 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
67 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"};
68 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
69 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
70 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
71 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
72 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
73 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)"};
74 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
75 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
76 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"};
77 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"};
78 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
79 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"};
80 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"};
81 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"};
82 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
83 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
84 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
85 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
86 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
87 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
88 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
89 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)"};
90 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)"};
91 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
92 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
93 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
94 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
96 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
97 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
98 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
100 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
101 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
102 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
103 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."};
104 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
105 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
106 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
107 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."};
108 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
109 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
110 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
111 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
112 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"};
113 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"};
114 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
115 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
117 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
118 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"};
120 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
121 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
122 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
123 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
124 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
125 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
126 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
127 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
129 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)"};
130 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"};
132 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
133 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
134 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
138 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
139 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
140 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
142 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)"};
143 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
144 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
145 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
146 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
147 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)"};
148 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)"};
149 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)"};
150 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)"};
152 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)"};
153 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
154 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"};
155 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
156 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
157 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
159 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
160 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
161 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
162 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
164 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
165 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
166 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
167 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
168 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
169 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
170 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
172 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
173 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
174 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
175 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)"};
177 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"};
179 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"};
181 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
183 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
184 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"};
185 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
186 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
187 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
188 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
189 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)"};
191 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
193 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)"};
195 extern cvar_t v_glslgamma;
197 extern qboolean v_flipped_state;
199 static struct r_bloomstate_s
204 int bloomwidth, bloomheight;
206 int screentexturewidth, screentextureheight;
207 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
209 int bloomtexturewidth, bloomtextureheight;
210 rtexture_t *texture_bloom;
212 // arrays for rendering the screen passes
213 float screentexcoord2f[8];
214 float bloomtexcoord2f[8];
215 float offsettexcoord2f[8];
217 r_viewport_t viewport;
221 r_waterstate_t r_waterstate;
223 /// shadow volume bsp struct with automatically growing nodes buffer
226 rtexture_t *r_texture_blanknormalmap;
227 rtexture_t *r_texture_white;
228 rtexture_t *r_texture_grey128;
229 rtexture_t *r_texture_black;
230 rtexture_t *r_texture_notexture;
231 rtexture_t *r_texture_whitecube;
232 rtexture_t *r_texture_normalizationcube;
233 rtexture_t *r_texture_fogattenuation;
234 rtexture_t *r_texture_fogheighttexture;
235 rtexture_t *r_texture_gammaramps;
236 unsigned int r_texture_gammaramps_serial;
237 //rtexture_t *r_texture_fogintensity;
238 rtexture_t *r_texture_reflectcube;
240 // TODO: hash lookups?
241 typedef struct cubemapinfo_s
248 int r_texture_numcubemaps;
249 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
251 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
252 unsigned int r_numqueries;
253 unsigned int r_maxqueries;
255 typedef struct r_qwskincache_s
257 char name[MAX_QPATH];
258 skinframe_t *skinframe;
262 static r_qwskincache_t *r_qwskincache;
263 static int r_qwskincache_size;
265 /// vertex coordinates for a quad that covers the screen exactly
266 extern const float r_screenvertex3f[12];
267 extern const float r_d3dscreenvertex3f[12];
268 const float r_screenvertex3f[12] =
275 const float r_d3dscreenvertex3f[12] =
283 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
286 for (i = 0;i < verts;i++)
297 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
300 for (i = 0;i < verts;i++)
310 // FIXME: move this to client?
313 if (gamemode == GAME_NEHAHRA)
315 Cvar_Set("gl_fogenable", "0");
316 Cvar_Set("gl_fogdensity", "0.2");
317 Cvar_Set("gl_fogred", "0.3");
318 Cvar_Set("gl_foggreen", "0.3");
319 Cvar_Set("gl_fogblue", "0.3");
321 r_refdef.fog_density = 0;
322 r_refdef.fog_red = 0;
323 r_refdef.fog_green = 0;
324 r_refdef.fog_blue = 0;
325 r_refdef.fog_alpha = 1;
326 r_refdef.fog_start = 0;
327 r_refdef.fog_end = 16384;
328 r_refdef.fog_height = 1<<30;
329 r_refdef.fog_fadedepth = 128;
330 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
333 static void R_BuildBlankTextures(void)
335 unsigned char data[4];
336 data[2] = 128; // normal X
337 data[1] = 128; // normal Y
338 data[0] = 255; // normal Z
339 data[3] = 128; // height
340 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
345 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
350 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
355 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
358 static void R_BuildNoTexture(void)
361 unsigned char pix[16][16][4];
362 // this makes a light grey/dark grey checkerboard texture
363 for (y = 0;y < 16;y++)
365 for (x = 0;x < 16;x++)
367 if ((y < 8) ^ (x < 8))
383 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
386 static void R_BuildWhiteCube(void)
388 unsigned char data[6*1*1*4];
389 memset(data, 255, sizeof(data));
390 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
393 static void R_BuildNormalizationCube(void)
397 vec_t s, t, intensity;
400 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
401 for (side = 0;side < 6;side++)
403 for (y = 0;y < NORMSIZE;y++)
405 for (x = 0;x < NORMSIZE;x++)
407 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
408 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
443 intensity = 127.0f / sqrt(DotProduct(v, v));
444 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
445 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
446 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
447 data[((side*64+y)*64+x)*4+3] = 255;
451 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
455 static void R_BuildFogTexture(void)
459 unsigned char data1[FOGWIDTH][4];
460 //unsigned char data2[FOGWIDTH][4];
463 r_refdef.fogmasktable_start = r_refdef.fog_start;
464 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
465 r_refdef.fogmasktable_range = r_refdef.fogrange;
466 r_refdef.fogmasktable_density = r_refdef.fog_density;
468 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
469 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
471 d = (x * r - r_refdef.fogmasktable_start);
472 if(developer_extra.integer)
473 Con_DPrintf("%f ", d);
475 if (r_fog_exp2.integer)
476 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
478 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
479 if(developer_extra.integer)
480 Con_DPrintf(" : %f ", alpha);
481 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
482 if(developer_extra.integer)
483 Con_DPrintf(" = %f\n", alpha);
484 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
487 for (x = 0;x < FOGWIDTH;x++)
489 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
494 //data2[x][0] = 255 - b;
495 //data2[x][1] = 255 - b;
496 //data2[x][2] = 255 - b;
499 if (r_texture_fogattenuation)
501 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
502 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
506 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
507 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
511 static void R_BuildFogHeightTexture(void)
513 unsigned char *inpixels;
521 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
522 if (r_refdef.fogheighttexturename[0])
523 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
526 r_refdef.fog_height_tablesize = 0;
527 if (r_texture_fogheighttexture)
528 R_FreeTexture(r_texture_fogheighttexture);
529 r_texture_fogheighttexture = NULL;
530 if (r_refdef.fog_height_table2d)
531 Mem_Free(r_refdef.fog_height_table2d);
532 r_refdef.fog_height_table2d = NULL;
533 if (r_refdef.fog_height_table1d)
534 Mem_Free(r_refdef.fog_height_table1d);
535 r_refdef.fog_height_table1d = NULL;
539 r_refdef.fog_height_tablesize = size;
540 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
541 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
542 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
544 // LordHavoc: now the magic - what is that table2d for? it is a cooked
545 // average fog color table accounting for every fog layer between a point
546 // and the camera. (Note: attenuation is handled separately!)
547 for (y = 0;y < size;y++)
549 for (x = 0;x < size;x++)
555 for (j = x;j <= y;j++)
557 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
563 for (j = x;j >= y;j--)
565 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
570 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
571 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
572 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
573 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
576 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
579 //=======================================================================================================================================================
581 static const char *builtinshaderstring =
582 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
583 "// written by Forest 'LordHavoc' Hale\n"
584 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
586 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
589 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
590 "#define USELIGHTMAP\n"
592 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
593 "#define USEEYEVECTOR\n"
596 "#ifdef USESHADOWMAP2D\n"
597 "# ifdef GL_EXT_gpu_shader4\n"
598 "# extension GL_EXT_gpu_shader4 : enable\n"
600 "# ifdef GL_ARB_texture_gather\n"
601 "# extension GL_ARB_texture_gather : enable\n"
603 "# ifdef GL_AMD_texture_texture4\n"
604 "# extension GL_AMD_texture_texture4 : enable\n"
609 "//#ifdef USESHADOWSAMPLER\n"
610 "//# extension GL_ARB_shadow : enable\n"
613 "//#ifdef __GLSL_CG_DATA_TYPES\n"
614 "//# define myhalf half\n"
615 "//# define myhalf2 half2\n"
616 "//# define myhalf3 half3\n"
617 "//# define myhalf4 half4\n"
619 "# define myhalf float\n"
620 "# define myhalf2 vec2\n"
621 "# define myhalf3 vec3\n"
622 "# define myhalf4 vec4\n"
625 "#ifdef VERTEX_SHADER\n"
626 "uniform mat4 ModelViewProjectionMatrix;\n"
629 "#ifdef MODE_DEPTH_OR_SHADOW\n"
630 "#ifdef VERTEX_SHADER\n"
633 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
636 "#else // !MODE_DEPTH_ORSHADOW\n"
641 "#ifdef MODE_SHOWDEPTH\n"
642 "#ifdef VERTEX_SHADER\n"
645 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
646 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
650 "#ifdef FRAGMENT_SHADER\n"
653 " gl_FragColor = gl_Color;\n"
656 "#else // !MODE_SHOWDEPTH\n"
661 "#ifdef MODE_POSTPROCESS\n"
662 "varying vec2 TexCoord1;\n"
663 "varying vec2 TexCoord2;\n"
665 "#ifdef VERTEX_SHADER\n"
668 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
669 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
671 " TexCoord2 = gl_MultiTexCoord4.xy;\n"
676 "#ifdef FRAGMENT_SHADER\n"
677 "uniform sampler2D Texture_First;\n"
679 "uniform sampler2D Texture_Second;\n"
680 "uniform vec4 BloomColorSubtract;\n"
682 "#ifdef USEGAMMARAMPS\n"
683 "uniform sampler2D Texture_GammaRamps;\n"
685 "#ifdef USESATURATION\n"
686 "uniform float Saturation;\n"
688 "#ifdef USEVIEWTINT\n"
689 "uniform vec4 ViewTintColor;\n"
691 "//uncomment these if you want to use them:\n"
692 "uniform vec4 UserVec1;\n"
693 "uniform vec4 UserVec2;\n"
694 "// uniform vec4 UserVec3;\n"
695 "// uniform vec4 UserVec4;\n"
696 "// uniform float ClientTime;\n"
697 "uniform vec2 PixelSize;\n"
700 " gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
702 " gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
704 "#ifdef USEVIEWTINT\n"
705 " gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
708 "#ifdef USEPOSTPROCESSING\n"
709 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
710 "// 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"
711 " float sobel = 1.0;\n"
712 " // vec2 ts = textureSize(Texture_First, 0);\n"
713 " // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
714 " vec2 px = PixelSize;\n"
715 " vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
716 " vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, 0.0)).rgb;\n"
717 " vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
718 " vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
719 " vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x, 0.0)).rgb;\n"
720 " vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
721 " vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
722 " vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2( 0.0,-px.y)).rgb;\n"
723 " vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
724 " vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
725 " vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2( 0.0, px.y)).rgb;\n"
726 " vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
727 " float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
728 " float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
729 " float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
730 " float px4 = 1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
731 " float px5 = 2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
732 " float px6 = 1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
733 " float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
734 " float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
735 " float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
736 " float py4 = 1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
737 " float py5 = 2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
738 " float py6 = 1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
739 " sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
740 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
741 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
742 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
743 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
744 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
745 " gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
746 " gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
749 "#ifdef USESATURATION\n"
750 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
751 " float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
752 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
753 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
756 "#ifdef USEGAMMARAMPS\n"
757 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
758 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
759 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
763 "#else // !MODE_POSTPROCESS\n"
768 "#ifdef MODE_GENERIC\n"
769 "#ifdef USEDIFFUSE\n"
770 "varying vec2 TexCoord1;\n"
772 "#ifdef USESPECULAR\n"
773 "varying vec2 TexCoord2;\n"
775 "#ifdef VERTEX_SHADER\n"
778 " gl_FrontColor = gl_Color;\n"
779 "#ifdef USEDIFFUSE\n"
780 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
782 "#ifdef USESPECULAR\n"
783 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
785 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
789 "#ifdef FRAGMENT_SHADER\n"
790 "#ifdef USEDIFFUSE\n"
791 "uniform sampler2D Texture_First;\n"
793 "#ifdef USESPECULAR\n"
794 "uniform sampler2D Texture_Second;\n"
799 " gl_FragColor = gl_Color;\n"
800 "#ifdef USEDIFFUSE\n"
801 " gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
804 "#ifdef USESPECULAR\n"
805 " vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
806 "# ifdef USECOLORMAPPING\n"
807 " gl_FragColor *= tex2;\n"
810 " gl_FragColor += tex2;\n"
812 "# ifdef USEVERTEXTEXTUREBLEND\n"
813 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
818 "#else // !MODE_GENERIC\n"
823 "#ifdef MODE_BLOOMBLUR\n"
824 "varying TexCoord;\n"
825 "#ifdef VERTEX_SHADER\n"
828 " gl_FrontColor = gl_Color;\n"
829 " TexCoord = gl_MultiTexCoord0.xy;\n"
830 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
834 "#ifdef FRAGMENT_SHADER\n"
835 "uniform sampler2D Texture_First;\n"
836 "uniform vec4 BloomBlur_Parameters;\n"
841 " vec2 tc = TexCoord;\n"
842 " vec3 color = texture2D(Texture_First, tc).rgb;\n"
843 " tc += BloomBlur_Parameters.xy;\n"
844 " for (i = 1;i < SAMPLES;i++)\n"
846 " color += texture2D(Texture_First, tc).rgb;\n"
847 " tc += BloomBlur_Parameters.xy;\n"
849 " gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
852 "#else // !MODE_BLOOMBLUR\n"
853 "#ifdef MODE_REFRACTION\n"
854 "varying vec2 TexCoord;\n"
855 "varying vec4 ModelViewProjectionPosition;\n"
856 "uniform mat4 TexMatrix;\n"
857 "#ifdef VERTEX_SHADER\n"
861 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
862 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
863 " ModelViewProjectionPosition = gl_Position;\n"
867 "#ifdef FRAGMENT_SHADER\n"
868 "uniform sampler2D Texture_Normal;\n"
869 "uniform sampler2D Texture_Refraction;\n"
870 "uniform sampler2D Texture_Reflection;\n"
872 "uniform vec4 DistortScaleRefractReflect;\n"
873 "uniform vec4 ScreenScaleRefractReflect;\n"
874 "uniform vec4 ScreenCenterRefractReflect;\n"
875 "uniform vec4 RefractColor;\n"
876 "uniform vec4 ReflectColor;\n"
877 "uniform float ReflectFactor;\n"
878 "uniform float ReflectOffset;\n"
882 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
883 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
884 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
885 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
886 " // FIXME temporary hack to detect the case that the reflection\n"
887 " // gets blackened at edges due to leaving the area that contains actual\n"
889 " // Remove this 'ack once we have a better way to stop this thing from\n"
891 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
892 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
893 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
894 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
895 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
896 " gl_FragColor = vec4(texture2D(Texture_Refraction, ScreenTexCoord).rgb, 1.0) * RefractColor;\n"
899 "#else // !MODE_REFRACTION\n"
904 "#ifdef MODE_WATER\n"
905 "varying vec2 TexCoord;\n"
906 "varying vec3 EyeVector;\n"
907 "varying vec4 ModelViewProjectionPosition;\n"
908 "#ifdef VERTEX_SHADER\n"
909 "uniform vec3 EyePosition;\n"
910 "uniform mat4 TexMatrix;\n"
914 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
915 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
916 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
917 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
918 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
919 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
920 " ModelViewProjectionPosition = gl_Position;\n"
924 "#ifdef FRAGMENT_SHADER\n"
925 "uniform sampler2D Texture_Normal;\n"
926 "uniform sampler2D Texture_Refraction;\n"
927 "uniform sampler2D Texture_Reflection;\n"
929 "uniform vec4 DistortScaleRefractReflect;\n"
930 "uniform vec4 ScreenScaleRefractReflect;\n"
931 "uniform vec4 ScreenCenterRefractReflect;\n"
932 "uniform vec4 RefractColor;\n"
933 "uniform vec4 ReflectColor;\n"
934 "uniform float ReflectFactor;\n"
935 "uniform float ReflectOffset;\n"
936 "uniform float ClientTime;\n"
937 "#ifdef USENORMALMAPSCROLLBLEND\n"
938 "uniform vec2 NormalmapScrollBlend;\n"
943 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
944 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
945 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
946 " //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
947 " // slight water animation via 2 layer scrolling (todo: tweak)\n"
948 " #ifdef USENORMALMAPSCROLLBLEND\n"
949 " vec3 normal = texture2D(Texture_Normal, (TexCoord + vec2(0.08, 0.08)*ClientTime*NormalmapScrollBlend.x*0.5)*NormalmapScrollBlend.y).rgb - vec3(1.0);\n"
950 " normal += texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime*NormalmapScrollBlend.x)*NormalmapScrollBlend.y*0.75).rgb;\n"
951 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(normal) + vec3(0.15)).xyxy * DistortScaleRefractReflect;\n"
953 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
955 " // FIXME temporary hack to detect the case that the reflection\n"
956 " // gets blackened at edges due to leaving the area that contains actual\n"
958 " // Remove this 'ack once we have a better way to stop this thing from\n"
960 " float f1 = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, 0.01)).rgb) / 0.002);\n"
961 " f1 *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, -0.01)).rgb) / 0.002);\n"
962 " f1 *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, 0.01)).rgb) / 0.002);\n"
963 " f1 *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, -0.01)).rgb) / 0.002);\n"
964 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f1);\n"
965 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, 0.005)).rgb) / 0.002);\n"
966 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, -0.005)).rgb) / 0.002);\n"
967 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, 0.005)).rgb) / 0.002);\n"
968 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, -0.005)).rgb) / 0.002);\n"
969 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
970 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
971 " gl_FragColor = mix(vec4(texture2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, vec4(texture2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
972 " gl_FragColor.a = f1 + 0.5;\n"
975 "#else // !MODE_WATER\n"
980 "// common definitions between vertex shader and fragment shader:\n"
982 "varying vec2 TexCoord;\n"
983 "#ifdef USEVERTEXTEXTUREBLEND\n"
984 "varying vec2 TexCoord2;\n"
986 "#ifdef USELIGHTMAP\n"
987 "varying vec2 TexCoordLightmap;\n"
990 "#ifdef MODE_LIGHTSOURCE\n"
991 "varying vec3 CubeVector;\n"
994 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
995 "varying vec3 LightVector;\n"
998 "#ifdef USEEYEVECTOR\n"
999 "varying vec3 EyeVector;\n"
1002 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
1005 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
1006 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
1007 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
1008 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
1011 "#ifdef USEREFLECTION\n"
1012 "varying vec4 ModelViewProjectionPosition;\n"
1014 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1015 "uniform vec3 LightPosition;\n"
1016 "varying vec4 ModelViewPosition;\n"
1019 "#ifdef MODE_LIGHTSOURCE\n"
1020 "uniform vec3 LightPosition;\n"
1022 "uniform vec3 EyePosition;\n"
1023 "#ifdef MODE_LIGHTDIRECTION\n"
1024 "uniform vec3 LightDir;\n"
1026 "uniform vec4 FogPlane;\n"
1028 "#ifdef USESHADOWMAPORTHO\n"
1029 "varying vec3 ShadowMapTC;\n"
1036 "// 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"
1038 "// fragment shader specific:\n"
1039 "#ifdef FRAGMENT_SHADER\n"
1041 "uniform sampler2D Texture_Normal;\n"
1042 "uniform sampler2D Texture_Color;\n"
1043 "uniform sampler2D Texture_Gloss;\n"
1045 "uniform sampler2D Texture_Glow;\n"
1047 "#ifdef USEVERTEXTEXTUREBLEND\n"
1048 "uniform sampler2D Texture_SecondaryNormal;\n"
1049 "uniform sampler2D Texture_SecondaryColor;\n"
1050 "uniform sampler2D Texture_SecondaryGloss;\n"
1052 "uniform sampler2D Texture_SecondaryGlow;\n"
1055 "#ifdef USECOLORMAPPING\n"
1056 "uniform sampler2D Texture_Pants;\n"
1057 "uniform sampler2D Texture_Shirt;\n"
1060 "#ifdef USEFOGHEIGHTTEXTURE\n"
1061 "uniform sampler2D Texture_FogHeightTexture;\n"
1063 "uniform sampler2D Texture_FogMask;\n"
1065 "#ifdef USELIGHTMAP\n"
1066 "uniform sampler2D Texture_Lightmap;\n"
1068 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1069 "uniform sampler2D Texture_Deluxemap;\n"
1071 "#ifdef USEREFLECTION\n"
1072 "uniform sampler2D Texture_Reflection;\n"
1075 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1076 "uniform sampler2D Texture_ScreenDepth;\n"
1077 "uniform sampler2D Texture_ScreenNormalMap;\n"
1079 "#ifdef USEDEFERREDLIGHTMAP\n"
1080 "uniform sampler2D Texture_ScreenDiffuse;\n"
1081 "uniform sampler2D Texture_ScreenSpecular;\n"
1084 "uniform myhalf3 Color_Pants;\n"
1085 "uniform myhalf3 Color_Shirt;\n"
1086 "uniform myhalf3 FogColor;\n"
1089 "uniform float FogRangeRecip;\n"
1090 "uniform float FogPlaneViewDist;\n"
1091 "uniform float FogHeightFade;\n"
1092 "vec3 FogVertex(vec3 surfacecolor)\n"
1094 " vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1095 " float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1097 "#ifdef USEFOGHEIGHTTEXTURE\n"
1098 " vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1099 " fogfrac = fogheightpixel.a;\n"
1100 " return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1102 "# ifdef USEFOGOUTSIDE\n"
1103 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1105 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1107 " return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1112 "#ifdef USEOFFSETMAPPING\n"
1113 "uniform float OffsetMapping_Scale;\n"
1114 "vec2 OffsetMapping(vec2 TexCoord)\n"
1116 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1117 " // 14 sample relief mapping: linear search and then binary search\n"
1118 " // this basically steps forward a small amount repeatedly until it finds\n"
1119 " // itself inside solid, then jitters forward and back using decreasing\n"
1120 " // amounts to find the impact\n"
1121 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1122 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1123 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1124 " vec3 RT = vec3(TexCoord, 1);\n"
1125 " OffsetVector *= 0.1;\n"
1126 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1127 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1128 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\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) - 0.5);\n"
1136 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
1137 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
1138 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
1139 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1142 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1143 " // this basically moves forward the full distance, and then backs up based\n"
1144 " // on height of samples\n"
1145 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1146 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1147 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1148 " TexCoord += OffsetVector;\n"
1149 " OffsetVector *= 0.333;\n"
1150 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1151 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1152 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1153 " return TexCoord;\n"
1156 "#endif // USEOFFSETMAPPING\n"
1158 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1159 "uniform sampler2D Texture_Attenuation;\n"
1160 "uniform samplerCube Texture_Cube;\n"
1163 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1165 "#ifdef USESHADOWMAP2D\n"
1166 "# ifdef USESHADOWSAMPLER\n"
1167 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1169 "uniform sampler2D Texture_ShadowMap2D;\n"
1173 "#ifdef USESHADOWMAPVSDCT\n"
1174 "uniform samplerCube Texture_CubeProjection;\n"
1177 "#if defined(USESHADOWMAP2D)\n"
1178 "uniform vec2 ShadowMap_TextureScale;\n"
1179 "uniform vec4 ShadowMap_Parameters;\n"
1182 "#if defined(USESHADOWMAP2D)\n"
1183 "# ifdef USESHADOWMAPORTHO\n"
1184 "# define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1186 "# ifdef USESHADOWMAPVSDCT\n"
1187 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1189 " vec3 adir = abs(dir);\n"
1190 " vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1191 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1192 " return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1195 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1197 " vec3 adir = abs(dir);\n"
1198 " float ma = adir.z;\n"
1199 " vec4 proj = vec4(dir, 2.5);\n"
1200 " if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1201 " if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1202 " vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1203 " 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"
1207 "#endif // defined(USESHADOWMAP2D)\n"
1209 "# ifdef USESHADOWMAP2D\n"
1210 "float ShadowMapCompare(vec3 dir)\n"
1212 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1215 "# ifdef USESHADOWSAMPLER\n"
1216 "# ifdef USESHADOWMAPPCF\n"
1217 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1218 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1219 " f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1221 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1224 "# ifdef USESHADOWMAPPCF\n"
1225 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1226 "# ifdef GL_ARB_texture_gather\n"
1227 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1229 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1231 " vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1232 "# if USESHADOWMAPPCF > 1\n"
1233 " vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1234 " vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1235 " vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1236 " vec4 group4 = step(shadowmaptc.z, texval(-2.0, 0.0));\n"
1237 " vec4 group5 = step(shadowmaptc.z, texval( 0.0, 0.0));\n"
1238 " vec4 group6 = step(shadowmaptc.z, texval( 2.0, 0.0));\n"
1239 " vec4 group7 = step(shadowmaptc.z, texval(-2.0, 2.0));\n"
1240 " vec4 group8 = step(shadowmaptc.z, texval( 0.0, 2.0));\n"
1241 " vec4 group9 = step(shadowmaptc.z, texval( 2.0, 2.0));\n"
1242 " vec4 locols = vec4(group1.ab, group3.ab);\n"
1243 " vec4 hicols = vec4(group7.rg, group9.rg);\n"
1244 " locols.yz += group2.ab;\n"
1245 " hicols.yz += group8.rg;\n"
1246 " vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1247 " vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1248 " mix(locols, hicols, offset.y);\n"
1249 " vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1250 " cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1251 " f = dot(cols, vec4(1.0/25.0));\n"
1253 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1254 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1255 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1256 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1257 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1258 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1259 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1262 "# ifdef GL_EXT_gpu_shader4\n"
1263 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1265 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1267 "# if USESHADOWMAPPCF > 1\n"
1268 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1269 " center *= ShadowMap_TextureScale;\n"
1270 " 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"
1271 " 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"
1272 " 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"
1273 " 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"
1274 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1275 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1277 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1278 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1279 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1280 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1281 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1282 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1286 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1289 "# ifdef USESHADOWMAPORTHO\n"
1290 " return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1296 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1297 "#endif // FRAGMENT_SHADER\n"
1302 "#ifdef MODE_DEFERREDGEOMETRY\n"
1303 "#ifdef VERTEX_SHADER\n"
1304 "uniform mat4 TexMatrix;\n"
1305 "#ifdef USEVERTEXTEXTUREBLEND\n"
1306 "uniform mat4 BackgroundTexMatrix;\n"
1308 "uniform mat4 ModelViewMatrix;\n"
1311 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1312 "#ifdef USEVERTEXTEXTUREBLEND\n"
1313 " gl_FrontColor = gl_Color;\n"
1314 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1317 " // transform unnormalized eye direction into tangent space\n"
1318 "#ifdef USEOFFSETMAPPING\n"
1319 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1320 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1321 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1322 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1325 " VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1326 " VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1327 " VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1328 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1330 "#endif // VERTEX_SHADER\n"
1332 "#ifdef FRAGMENT_SHADER\n"
1335 "#ifdef USEOFFSETMAPPING\n"
1336 " // apply offsetmapping\n"
1337 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1338 "#define TexCoord TexCoordOffset\n"
1341 "#ifdef USEALPHAKILL\n"
1342 " if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1346 "#ifdef USEVERTEXTEXTUREBLEND\n"
1347 " float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1348 " float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1349 " //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1350 " //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1353 "#ifdef USEVERTEXTEXTUREBLEND\n"
1354 " vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1355 " float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1357 " vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1358 " float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1361 " gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1363 "#endif // FRAGMENT_SHADER\n"
1364 "#else // !MODE_DEFERREDGEOMETRY\n"
1369 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1370 "#ifdef VERTEX_SHADER\n"
1371 "uniform mat4 ModelViewMatrix;\n"
1374 " ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1375 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1377 "#endif // VERTEX_SHADER\n"
1379 "#ifdef FRAGMENT_SHADER\n"
1380 "uniform mat4 ViewToLight;\n"
1381 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1382 "uniform vec2 ScreenToDepth;\n"
1383 "uniform myhalf3 DeferredColor_Ambient;\n"
1384 "uniform myhalf3 DeferredColor_Diffuse;\n"
1385 "#ifdef USESPECULAR\n"
1386 "uniform myhalf3 DeferredColor_Specular;\n"
1387 "uniform myhalf SpecularPower;\n"
1389 "uniform myhalf2 PixelToScreenTexCoord;\n"
1392 " // calculate viewspace pixel position\n"
1393 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1395 " position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1396 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1397 " // decode viewspace pixel normal\n"
1398 " myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1399 " myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1400 " // surfacenormal = pixel normal in viewspace\n"
1401 " // LightVector = pixel to light in viewspace\n"
1402 " // CubeVector = position in lightspace\n"
1403 " // eyevector = pixel to view in viewspace\n"
1404 " vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1405 " myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1406 "#ifdef USEDIFFUSE\n"
1407 " // calculate diffuse shading\n"
1408 " myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1409 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1411 "#ifdef USESPECULAR\n"
1412 " // calculate directional shading\n"
1413 " vec3 eyevector = position * -1.0;\n"
1414 "# ifdef USEEXACTSPECULARMATH\n"
1415 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1417 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1418 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1422 "#if defined(USESHADOWMAP2D)\n"
1423 " fade *= ShadowMapCompare(CubeVector);\n"
1426 "#ifdef USEDIFFUSE\n"
1427 " gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1429 " gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1431 "#ifdef USESPECULAR\n"
1432 " gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1434 " gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1437 "# ifdef USECUBEFILTER\n"
1438 " vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1439 " gl_FragData[0].rgb *= cubecolor;\n"
1440 " gl_FragData[1].rgb *= cubecolor;\n"
1443 "#endif // FRAGMENT_SHADER\n"
1444 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1449 "#ifdef VERTEX_SHADER\n"
1450 "uniform mat4 TexMatrix;\n"
1451 "#ifdef USEVERTEXTEXTUREBLEND\n"
1452 "uniform mat4 BackgroundTexMatrix;\n"
1454 "#ifdef MODE_LIGHTSOURCE\n"
1455 "uniform mat4 ModelToLight;\n"
1457 "#ifdef USESHADOWMAPORTHO\n"
1458 "uniform mat4 ShadowMapMatrix;\n"
1462 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1463 " gl_FrontColor = gl_Color;\n"
1465 " // copy the surface texcoord\n"
1466 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1467 "#ifdef USEVERTEXTEXTUREBLEND\n"
1468 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1470 "#ifdef USELIGHTMAP\n"
1471 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1474 "#ifdef MODE_LIGHTSOURCE\n"
1475 " // transform vertex position into light attenuation/cubemap space\n"
1476 " // (-1 to +1 across the light box)\n"
1477 " CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1479 "# ifdef USEDIFFUSE\n"
1480 " // transform unnormalized light direction into tangent space\n"
1481 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
1482 " // normalize it per pixel)\n"
1483 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1484 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1485 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1486 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1490 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1491 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1492 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1493 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1496 " // transform unnormalized eye direction into tangent space\n"
1497 "#ifdef USEEYEVECTOR\n"
1498 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1499 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1500 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1501 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1505 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1506 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1509 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1510 " VectorS = gl_MultiTexCoord1.xyz;\n"
1511 " VectorT = gl_MultiTexCoord2.xyz;\n"
1512 " VectorR = gl_MultiTexCoord3.xyz;\n"
1515 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1516 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1518 "#ifdef USESHADOWMAPORTHO\n"
1519 " ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1522 "#ifdef USEREFLECTION\n"
1523 " ModelViewProjectionPosition = gl_Position;\n"
1526 "#endif // VERTEX_SHADER\n"
1531 "#ifdef FRAGMENT_SHADER\n"
1532 "#ifdef USEDEFERREDLIGHTMAP\n"
1533 "uniform myhalf2 PixelToScreenTexCoord;\n"
1534 "uniform myhalf3 DeferredMod_Diffuse;\n"
1535 "uniform myhalf3 DeferredMod_Specular;\n"
1537 "uniform myhalf3 Color_Ambient;\n"
1538 "uniform myhalf3 Color_Diffuse;\n"
1539 "uniform myhalf3 Color_Specular;\n"
1540 "uniform myhalf SpecularPower;\n"
1542 "uniform myhalf3 Color_Glow;\n"
1544 "uniform myhalf Alpha;\n"
1545 "#ifdef USEREFLECTION\n"
1546 "uniform vec4 DistortScaleRefractReflect;\n"
1547 "uniform vec4 ScreenScaleRefractReflect;\n"
1548 "uniform vec4 ScreenCenterRefractReflect;\n"
1549 "uniform myhalf4 ReflectColor;\n"
1551 "#ifdef USEREFLECTCUBE\n"
1552 "uniform mat4 ModelToReflectCube;\n"
1553 "uniform sampler2D Texture_ReflectMask;\n"
1554 "uniform samplerCube Texture_ReflectCube;\n"
1556 "#ifdef MODE_LIGHTDIRECTION\n"
1557 "uniform myhalf3 LightColor;\n"
1559 "#ifdef MODE_LIGHTSOURCE\n"
1560 "uniform myhalf3 LightColor;\n"
1564 "#ifdef USEOFFSETMAPPING\n"
1565 " // apply offsetmapping\n"
1566 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1567 "#define TexCoord TexCoordOffset\n"
1570 " // combine the diffuse textures (base, pants, shirt)\n"
1571 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1572 "#ifdef USEALPHAKILL\n"
1573 " if (color.a < 0.5)\n"
1576 " color.a *= Alpha;\n"
1577 "#ifdef USECOLORMAPPING\n"
1578 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1580 "#ifdef USEVERTEXTEXTUREBLEND\n"
1581 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1582 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1583 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1584 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1586 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1589 " // get the surface normal\n"
1590 "#ifdef USEVERTEXTEXTUREBLEND\n"
1591 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1593 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1596 " // get the material colors\n"
1597 " myhalf3 diffusetex = color.rgb;\n"
1598 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1599 "# ifdef USEVERTEXTEXTUREBLEND\n"
1600 " myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1602 " myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1606 "#ifdef USEREFLECTCUBE\n"
1607 " vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1608 " vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1609 " vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1610 " diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1616 "#ifdef MODE_LIGHTSOURCE\n"
1617 " // light source\n"
1618 "#ifdef USEDIFFUSE\n"
1619 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1620 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1621 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1622 "#ifdef USESPECULAR\n"
1623 "#ifdef USEEXACTSPECULARMATH\n"
1624 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1626 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1627 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1629 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1632 " color.rgb = diffusetex * Color_Ambient;\n"
1634 " color.rgb *= LightColor;\n"
1635 " color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1636 "#if defined(USESHADOWMAP2D)\n"
1637 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1639 "# ifdef USECUBEFILTER\n"
1640 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1642 "#endif // MODE_LIGHTSOURCE\n"
1647 "#ifdef MODE_LIGHTDIRECTION\n"
1649 "#ifdef USEDIFFUSE\n"
1650 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1652 "#define lightcolor LightColor\n"
1653 "#endif // MODE_LIGHTDIRECTION\n"
1654 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1656 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1657 " myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1658 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1659 " // convert modelspace light vector to tangentspace\n"
1660 " myhalf3 lightnormal;\n"
1661 " lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1662 " lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1663 " lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1664 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1665 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1666 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1667 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1668 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1669 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1670 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1671 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1672 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1673 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1674 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1675 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1677 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1678 " myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1679 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1685 "#ifdef MODE_FAKELIGHT\n"
1687 "myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
1688 "myhalf3 lightcolor = myhalf3(1.0);\n"
1689 "#endif // MODE_FAKELIGHT\n"
1694 "#ifdef MODE_LIGHTMAP\n"
1695 " color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1696 "#endif // MODE_LIGHTMAP\n"
1697 "#ifdef MODE_VERTEXCOLOR\n"
1698 " color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1699 "#endif // MODE_VERTEXCOLOR\n"
1700 "#ifdef MODE_FLATCOLOR\n"
1701 " color.rgb = diffusetex * Color_Ambient;\n"
1702 "#endif // MODE_FLATCOLOR\n"
1708 "# ifdef USEDIFFUSE\n"
1709 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1710 "# ifdef USESPECULAR\n"
1711 "# ifdef USEEXACTSPECULARMATH\n"
1712 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1714 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1715 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1717 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1719 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1722 " color.rgb = diffusetex * Color_Ambient;\n"
1726 "#ifdef USESHADOWMAPORTHO\n"
1727 " color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1730 "#ifdef USEDEFERREDLIGHTMAP\n"
1731 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1732 " color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1733 " color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1737 "#ifdef USEVERTEXTEXTUREBLEND\n"
1738 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1740 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1745 " color.rgb = FogVertex(color.rgb);\n"
1748 " // 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"
1749 "#ifdef USEREFLECTION\n"
1750 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1751 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1752 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1753 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1754 " // FIXME temporary hack to detect the case that the reflection\n"
1755 " // gets blackened at edges due to leaving the area that contains actual\n"
1757 " // Remove this 'ack once we have a better way to stop this thing from\n"
1759 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1760 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1761 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1762 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1763 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1764 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1767 " gl_FragColor = vec4(color);\n"
1769 "#endif // FRAGMENT_SHADER\n"
1771 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1772 "#endif // !MODE_DEFERREDGEOMETRY\n"
1773 "#endif // !MODE_WATER\n"
1774 "#endif // !MODE_REFRACTION\n"
1775 "#endif // !MODE_BLOOMBLUR\n"
1776 "#endif // !MODE_GENERIC\n"
1777 "#endif // !MODE_POSTPROCESS\n"
1778 "#endif // !MODE_SHOWDEPTH\n"
1779 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1783 =========================================================================================================================================================
1787 =========================================================================================================================================================
1791 =========================================================================================================================================================
1795 =========================================================================================================================================================
1799 =========================================================================================================================================================
1803 =========================================================================================================================================================
1807 =========================================================================================================================================================
1810 const char *builtincgshaderstring =
1811 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1812 "// written by Forest 'LordHavoc' Hale\n"
1813 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1815 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1816 "#if defined(USEREFLECTION)\n"
1817 "#undef USESHADOWMAPORTHO\n"
1820 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1823 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1824 "#define USELIGHTMAP\n"
1826 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
1827 "#define USEEYEVECTOR\n"
1830 "#ifdef FRAGMENT_SHADER\n"
1832 "//#undef USESHADOWMAPPCF\n"
1833 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1834 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1836 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1840 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1841 "#ifdef VERTEX_SHADER\n"
1844 "float4 gl_Vertex : POSITION,\n"
1845 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1846 "out float4 gl_Position : POSITION,\n"
1847 "out float Depth : TEXCOORD0\n"
1850 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1851 " Depth = gl_Position.z;\n"
1855 "#ifdef FRAGMENT_SHADER\n"
1858 "float Depth : TEXCOORD0,\n"
1859 "out float4 gl_FragColor : COLOR\n"
1862 "// float3 temp = float3(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0));\n"
1863 " float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
1864 " temp.yz -= floor(temp.yz);\n"
1865 " gl_FragColor = temp;\n"
1866 "// gl_FragColor = float4(Depth,0,0,0);\n"
1869 "#else // !MODE_DEPTH_ORSHADOW\n"
1874 "#ifdef MODE_SHOWDEPTH\n"
1875 "#ifdef VERTEX_SHADER\n"
1878 "float4 gl_Vertex : POSITION,\n"
1879 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1880 "out float4 gl_Position : POSITION,\n"
1881 "out float4 gl_FrontColor : COLOR0\n"
1884 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1885 " gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1889 "#ifdef FRAGMENT_SHADER\n"
1892 "float4 gl_FrontColor : COLOR0,\n"
1893 "out float4 gl_FragColor : COLOR\n"
1896 " gl_FragColor = gl_FrontColor;\n"
1899 "#else // !MODE_SHOWDEPTH\n"
1904 "#ifdef MODE_POSTPROCESS\n"
1906 "#ifdef VERTEX_SHADER\n"
1909 "float4 gl_Vertex : POSITION,\n"
1910 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1911 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1912 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1913 "out float4 gl_Position : POSITION,\n"
1914 "out float2 TexCoord1 : TEXCOORD0,\n"
1915 "out float2 TexCoord2 : TEXCOORD1\n"
1918 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1919 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
1921 " TexCoord2 = gl_MultiTexCoord4.xy;\n"
1926 "#ifdef FRAGMENT_SHADER\n"
1929 "float2 TexCoord1 : TEXCOORD0,\n"
1930 "float2 TexCoord2 : TEXCOORD1,\n"
1931 "uniform sampler Texture_First : register(s0),\n"
1933 "uniform sampler Texture_Second : register(s1),\n"
1935 "#ifdef USEGAMMARAMPS\n"
1936 "uniform sampler Texture_GammaRamps : register(s2),\n"
1938 "#ifdef USESATURATION\n"
1939 "uniform float Saturation : register(c30),\n"
1941 "#ifdef USEVIEWTINT\n"
1942 "uniform float4 ViewTintColor : register(c41),\n"
1944 "uniform float4 UserVec1 : register(c37),\n"
1945 "uniform float4 UserVec2 : register(c38),\n"
1946 "uniform float4 UserVec3 : register(c39),\n"
1947 "uniform float4 UserVec4 : register(c40),\n"
1948 "uniform float ClientTime : register(c2),\n"
1949 "uniform float2 PixelSize : register(c25),\n"
1950 "uniform float4 BloomColorSubtract : register(c43),\n"
1951 "out float4 gl_FragColor : COLOR\n"
1954 " gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1956 " gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
1958 "#ifdef USEVIEWTINT\n"
1959 " gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1962 "#ifdef USEPOSTPROCESSING\n"
1963 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1964 "// 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"
1965 " float sobel = 1.0;\n"
1966 " // float2 ts = textureSize(Texture_First, 0);\n"
1967 " // float2 px = float2(1/ts.x, 1/ts.y);\n"
1968 " float2 px = PixelSize;\n"
1969 " float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1970 " float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x, 0.0)).rgb;\n"
1971 " float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1972 " float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1973 " float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x, 0.0)).rgb;\n"
1974 " float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1975 " float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1976 " float3 y2 = tex2D(Texture_First, TexCoord1 + float2( 0.0,-px.y)).rgb;\n"
1977 " float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1978 " float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1979 " float3 y5 = tex2D(Texture_First, TexCoord1 + float2( 0.0, px.y)).rgb;\n"
1980 " float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1981 " float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
1982 " float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
1983 " float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
1984 " float px4 = 1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
1985 " float px5 = 2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
1986 " float px6 = 1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
1987 " float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
1988 " float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
1989 " float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
1990 " float py4 = 1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
1991 " float py5 = 2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
1992 " float py6 = 1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
1993 " sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
1994 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1995 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1996 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1997 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107, 0.707107)) * UserVec1.y;\n"
1998 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990, 0.891007)) * UserVec1.y;\n"
1999 " gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2000 " gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2003 "#ifdef USESATURATION\n"
2004 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2005 " float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2006 " //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2007 " gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2010 "#ifdef USEGAMMARAMPS\n"
2011 " gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2012 " gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2013 " gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2017 "#else // !MODE_POSTPROCESS\n"
2022 "#ifdef MODE_GENERIC\n"
2023 "#ifdef VERTEX_SHADER\n"
2026 "float4 gl_Vertex : POSITION,\n"
2027 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2028 "float4 gl_Color : COLOR0,\n"
2029 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2030 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2031 "out float4 gl_Position : POSITION,\n"
2032 "#ifdef USEDIFFUSE\n"
2033 "out float2 TexCoord1 : TEXCOORD0,\n"
2035 "#ifdef USESPECULAR\n"
2036 "out float2 TexCoord2 : TEXCOORD1,\n"
2038 "out float4 gl_FrontColor : COLOR\n"
2042 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2044 " gl_FrontColor = gl_Color; // Cg is forward\n"
2046 "#ifdef USEDIFFUSE\n"
2047 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
2049 "#ifdef USESPECULAR\n"
2050 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
2052 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2056 "#ifdef FRAGMENT_SHADER\n"
2060 "float4 gl_FrontColor : COLOR0,\n"
2061 "float2 TexCoord1 : TEXCOORD0,\n"
2062 "float2 TexCoord2 : TEXCOORD1,\n"
2063 "#ifdef USEDIFFUSE\n"
2064 "uniform sampler Texture_First : register(s0),\n"
2066 "#ifdef USESPECULAR\n"
2067 "uniform sampler Texture_Second : register(s1),\n"
2069 "out float4 gl_FragColor : COLOR\n"
2072 " gl_FragColor = gl_FrontColor;\n"
2073 "#ifdef USEDIFFUSE\n"
2074 " gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2077 "#ifdef USESPECULAR\n"
2078 " float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2079 "# ifdef USECOLORMAPPING\n"
2080 " gl_FragColor *= tex2;\n"
2083 " gl_FragColor += tex2;\n"
2085 "# ifdef USEVERTEXTEXTUREBLEND\n"
2086 " gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2091 "#else // !MODE_GENERIC\n"
2096 "#ifdef MODE_BLOOMBLUR\n"
2097 "#ifdef VERTEX_SHADER\n"
2100 "float4 gl_Vertex : POSITION,\n"
2101 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2102 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2103 "out float4 gl_Position : POSITION,\n"
2104 "out float2 TexCoord : TEXCOORD0\n"
2107 " TexCoord = gl_MultiTexCoord0.xy;\n"
2108 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2112 "#ifdef FRAGMENT_SHADER\n"
2116 "float2 TexCoord : TEXCOORD0,\n"
2117 "uniform sampler Texture_First : register(s0),\n"
2118 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2119 "out float4 gl_FragColor : COLOR\n"
2123 " float2 tc = TexCoord;\n"
2124 " float3 color = tex2D(Texture_First, tc).rgb;\n"
2125 " tc += BloomBlur_Parameters.xy;\n"
2126 " for (i = 1;i < SAMPLES;i++)\n"
2128 " color += tex2D(Texture_First, tc).rgb;\n"
2129 " tc += BloomBlur_Parameters.xy;\n"
2131 " gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2134 "#else // !MODE_BLOOMBLUR\n"
2135 "#ifdef MODE_REFRACTION\n"
2136 "#ifdef VERTEX_SHADER\n"
2139 "float4 gl_Vertex : POSITION,\n"
2140 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2141 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2142 "uniform float4x4 TexMatrix : register(c0),\n"
2143 "uniform float3 EyePosition : register(c24),\n"
2144 "out float4 gl_Position : POSITION,\n"
2145 "out float2 TexCoord : TEXCOORD0,\n"
2146 "out float3 EyeVector : TEXCOORD1,\n"
2147 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2150 " TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2151 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2152 " ModelViewProjectionPosition = gl_Position;\n"
2156 "#ifdef FRAGMENT_SHADER\n"
2159 "float2 TexCoord : TEXCOORD0,\n"
2160 "float3 EyeVector : TEXCOORD1,\n"
2161 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2162 "uniform sampler Texture_Normal : register(s0),\n"
2163 "uniform sampler Texture_Refraction : register(s3),\n"
2164 "uniform sampler Texture_Reflection : register(s7),\n"
2165 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2166 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2167 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2168 "uniform float4 RefractColor : register(c29),\n"
2169 "out float4 gl_FragColor : COLOR\n"
2172 " float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2173 " //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2174 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2175 " float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.xy;\n"
2176 " // FIXME temporary hack to detect the case that the reflection\n"
2177 " // gets blackened at edges due to leaving the area that contains actual\n"
2179 " // Remove this 'ack once we have a better way to stop this thing from\n"
2181 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2182 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2183 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2184 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2185 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2186 " gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
2189 "#else // !MODE_REFRACTION\n"
2194 "#ifdef MODE_WATER\n"
2195 "#ifdef VERTEX_SHADER\n"
2199 "float4 gl_Vertex : POSITION,\n"
2200 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2201 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2202 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2203 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2204 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2205 "uniform float4x4 TexMatrix : register(c0),\n"
2206 "uniform float3 EyePosition : register(c24),\n"
2207 "out float4 gl_Position : POSITION,\n"
2208 "out float2 TexCoord : TEXCOORD0,\n"
2209 "out float3 EyeVector : TEXCOORD1,\n"
2210 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2213 " TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2214 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2215 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2216 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2217 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2218 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2219 " ModelViewProjectionPosition = gl_Position;\n"
2223 "#ifdef FRAGMENT_SHADER\n"
2226 "float2 TexCoord : TEXCOORD0,\n"
2227 "float3 EyeVector : TEXCOORD1,\n"
2228 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2229 "uniform sampler Texture_Normal : register(s0),\n"
2230 "uniform sampler Texture_Refraction : register(s3),\n"
2231 "uniform sampler Texture_Reflection : register(s7),\n"
2232 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2233 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2234 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2235 "uniform float4 RefractColor : register(c29),\n"
2236 "uniform float4 ReflectColor : register(c26),\n"
2237 "uniform float ReflectFactor : register(c27),\n"
2238 "uniform float ReflectOffset : register(c28),\n"
2239 "out float4 gl_FragColor : COLOR\n"
2242 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2243 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2244 " float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2245 " //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2246 " float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2247 " // FIXME temporary hack to detect the case that the reflection\n"
2248 " // gets blackened at edges due to leaving the area that contains actual\n"
2250 " // Remove this 'ack once we have a better way to stop this thing from\n"
2252 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2253 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2254 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2255 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2256 " ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2257 " f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2258 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2259 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2260 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2261 " ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2262 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2263 " gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
2266 "#else // !MODE_WATER\n"
2271 "// 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"
2273 "// fragment shader specific:\n"
2274 "#ifdef FRAGMENT_SHADER\n"
2277 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2280 "#ifdef USEFOGHEIGHTTEXTURE\n"
2281 " float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2282 " fogfrac = fogheightpixel.a;\n"
2283 " return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2285 "# ifdef USEFOGOUTSIDE\n"
2286 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2288 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2290 " return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2295 "#ifdef USEOFFSETMAPPING\n"
2296 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2298 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2299 " // 14 sample relief mapping: linear search and then binary search\n"
2300 " // this basically steps forward a small amount repeatedly until it finds\n"
2301 " // itself inside solid, then jitters forward and back using decreasing\n"
2302 " // amounts to find the impact\n"
2303 " //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2304 " //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2305 " float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2306 " float3 RT = float3(TexCoord, 1);\n"
2307 " OffsetVector *= 0.1;\n"
2308 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2309 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2310 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2311 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2312 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2313 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2314 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2315 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2316 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2317 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
2318 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
2319 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
2320 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
2321 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2324 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2325 " // this basically moves forward the full distance, and then backs up based\n"
2326 " // on height of samples\n"
2327 " //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2328 " //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2329 " float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2330 " TexCoord += OffsetVector;\n"
2331 " OffsetVector *= 0.333;\n"
2332 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2333 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2334 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2335 " return TexCoord;\n"
2338 "#endif // USEOFFSETMAPPING\n"
2340 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2341 "#if defined(USESHADOWMAP2D)\n"
2342 "# ifdef USESHADOWMAPORTHO\n"
2343 "# define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2345 "# ifdef USESHADOWMAPVSDCT\n"
2346 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2348 " float3 adir = abs(dir);\n"
2349 " float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2350 " float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2351 " return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2354 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2356 " float3 adir = abs(dir);\n"
2357 " float ma = adir.z;\n"
2358 " float4 proj = float4(dir, 2.5);\n"
2359 " if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2360 " if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2362 " return float3(proj.xy * ShadowMap_Parameters.x / ma + float2(0.5,0.5) + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, ma + 64 * ShadowMap_Parameters.w);\n"
2364 " float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2365 " 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"
2370 "#endif // defined(USESHADOWMAP2D)\n"
2372 "# ifdef USESHADOWMAP2D\n"
2373 "#ifdef USESHADOWMAPVSDCT\n"
2374 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2376 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2379 "#ifdef USESHADOWMAPVSDCT\n"
2380 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2382 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2386 "# ifdef USESHADOWSAMPLER\n"
2387 "# ifdef USESHADOWMAPPCF\n"
2388 "# define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r \n"
2389 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2390 " f = dot(float4(0.25,0.25,0.25,0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2392 " f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2395 "# ifdef USESHADOWMAPPCF\n"
2396 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2397 "# ifdef GL_ARB_texture_gather\n"
2398 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2400 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2402 " float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2403 "# if USESHADOWMAPPCF > 1\n"
2404 " float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2405 " float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2406 " float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2407 " float4 group4 = step(shadowmaptc.z, texval(-2.0, 0.0));\n"
2408 " float4 group5 = step(shadowmaptc.z, texval( 0.0, 0.0));\n"
2409 " float4 group6 = step(shadowmaptc.z, texval( 2.0, 0.0));\n"
2410 " float4 group7 = step(shadowmaptc.z, texval(-2.0, 2.0));\n"
2411 " float4 group8 = step(shadowmaptc.z, texval( 0.0, 2.0));\n"
2412 " float4 group9 = step(shadowmaptc.z, texval( 2.0, 2.0));\n"
2413 " float4 locols = float4(group1.ab, group3.ab);\n"
2414 " float4 hicols = float4(group7.rg, group9.rg);\n"
2415 " locols.yz += group2.ab;\n"
2416 " hicols.yz += group8.rg;\n"
2417 " float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2418 " float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2419 " lerp(locols, hicols, offset.y);\n"
2420 " float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2421 " cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2422 " f = dot(cols, float4(1.0/25.0));\n"
2424 " float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2425 " float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2426 " float4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
2427 " float4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
2428 " float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2429 " lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2430 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2433 "# ifdef GL_EXT_gpu_shader4\n"
2434 "# define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2436 "# define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r \n"
2438 "# if USESHADOWMAPPCF > 1\n"
2439 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2440 " center *= ShadowMap_TextureScale;\n"
2441 " 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"
2442 " 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"
2443 " 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"
2444 " 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"
2445 " float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2446 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2448 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2449 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2450 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2451 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2452 " float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2453 " f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2457 " f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2460 "# ifdef USESHADOWMAPORTHO\n"
2461 " return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2467 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2468 "#endif // FRAGMENT_SHADER\n"
2473 "#ifdef MODE_DEFERREDGEOMETRY\n"
2474 "#ifdef VERTEX_SHADER\n"
2477 "float4 gl_Vertex : POSITION,\n"
2478 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2479 "#ifdef USEVERTEXTEXTUREBLEND\n"
2480 "float4 gl_Color : COLOR0,\n"
2482 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2483 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2484 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2485 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2486 "uniform float4x4 TexMatrix : register(c0),\n"
2487 "#ifdef USEVERTEXTEXTUREBLEND\n"
2488 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2490 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2491 "#ifdef USEOFFSETMAPPING\n"
2492 "uniform float3 EyePosition : register(c24),\n"
2494 "out float4 gl_Position : POSITION,\n"
2495 "#ifdef USEVERTEXTEXTUREBLEND\n"
2496 "out float4 gl_FrontColor : COLOR,\n"
2498 "out float4 TexCoordBoth : TEXCOORD0,\n"
2499 "#ifdef USEOFFSETMAPPING\n"
2500 "out float3 EyeVector : TEXCOORD2,\n"
2502 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2503 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2504 "out float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\n"
2507 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2508 "#ifdef USEVERTEXTEXTUREBLEND\n"
2510 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2512 " gl_FrontColor = gl_Color; // Cg is forward\n"
2514 " TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2517 " // transform unnormalized eye direction into tangent space\n"
2518 "#ifdef USEOFFSETMAPPING\n"
2519 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2520 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2521 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2522 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2525 " VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2526 " VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2527 " VectorR.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2528 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2529 " VectorR.w = gl_Position.z;\n"
2531 "#endif // VERTEX_SHADER\n"
2533 "#ifdef FRAGMENT_SHADER\n"
2536 "float4 TexCoordBoth : TEXCOORD0,\n"
2537 "float3 EyeVector : TEXCOORD2,\n"
2538 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2539 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2540 "float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
2541 "uniform sampler Texture_Normal : register(s0),\n"
2542 "#ifdef USEALPHAKILL\n"
2543 "uniform sampler Texture_Color : register(s1),\n"
2545 "uniform sampler Texture_Gloss : register(s2),\n"
2546 "#ifdef USEVERTEXTEXTUREBLEND\n"
2547 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2548 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2550 "#ifdef USEOFFSETMAPPING\n"
2551 "uniform float OffsetMapping_Scale : register(c24),\n"
2553 "uniform half SpecularPower : register(c36),\n"
2555 "out float4 gl_FragData0 : COLOR0,\n"
2556 "out float4 gl_FragData1 : COLOR1\n"
2558 "out float4 gl_FragColor : COLOR\n"
2562 " float2 TexCoord = TexCoordBoth.xy;\n"
2563 "#ifdef USEOFFSETMAPPING\n"
2564 " // apply offsetmapping\n"
2565 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2566 "#define TexCoord TexCoordOffset\n"
2569 "#ifdef USEALPHAKILL\n"
2570 " if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2574 "#ifdef USEVERTEXTEXTUREBLEND\n"
2575 " float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2576 " float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2577 " //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2578 " //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2581 "#ifdef USEVERTEXTEXTUREBLEND\n"
2582 " float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2583 " float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2585 " float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2586 " float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2590 " gl_FragData0 = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR.xyz) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2591 " float Depth = VectorR.w / 256.0;\n"
2592 " float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
2593 "// float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
2594 " depthcolor.yz -= floor(depthcolor.yz);\n"
2595 " gl_FragData1 = depthcolor;\n"
2597 " gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2600 "#endif // FRAGMENT_SHADER\n"
2601 "#else // !MODE_DEFERREDGEOMETRY\n"
2606 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2607 "#ifdef VERTEX_SHADER\n"
2610 "float4 gl_Vertex : POSITION,\n"
2611 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2612 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2613 "out float4 gl_Position : POSITION,\n"
2614 "out float4 ModelViewPosition : TEXCOORD0\n"
2617 " ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2618 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2620 "#endif // VERTEX_SHADER\n"
2622 "#ifdef FRAGMENT_SHADER\n"
2626 "float2 Pixel : VPOS,\n"
2628 "float2 Pixel : WPOS,\n"
2630 "float4 ModelViewPosition : TEXCOORD0,\n"
2631 "uniform float4x4 ViewToLight : register(c44),\n"
2632 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2633 "uniform float3 LightPosition : register(c23),\n"
2634 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2635 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2636 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2637 "#ifdef USESPECULAR\n"
2638 "uniform half3 DeferredColor_Specular : register(c11),\n"
2639 "uniform half SpecularPower : register(c36),\n"
2641 "uniform sampler Texture_Attenuation : register(s9),\n"
2642 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2643 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2645 "#ifdef USECUBEFILTER\n"
2646 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2649 "#ifdef USESHADOWMAP2D\n"
2650 "# ifdef USESHADOWSAMPLER\n"
2651 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2653 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2657 "#ifdef USESHADOWMAPVSDCT\n"
2658 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2661 "#if defined(USESHADOWMAP2D)\n"
2662 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2663 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2666 "out float4 gl_FragData0 : COLOR0,\n"
2667 "out float4 gl_FragData1 : COLOR1\n"
2670 " // calculate viewspace pixel position\n"
2671 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2672 " //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2673 " float3 position;\n"
2675 " position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
2677 " position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2679 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2680 " // decode viewspace pixel normal\n"
2681 " half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2682 " half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2683 " // surfacenormal = pixel normal in viewspace\n"
2684 " // LightVector = pixel to light in viewspace\n"
2685 " // CubeVector = position in lightspace\n"
2686 " // eyevector = pixel to view in viewspace\n"
2687 " float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2688 " half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2689 "#ifdef USEDIFFUSE\n"
2690 " // calculate diffuse shading\n"
2691 " half3 lightnormal = half3(normalize(LightPosition - position));\n"
2692 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2694 "#ifdef USESPECULAR\n"
2695 " // calculate directional shading\n"
2696 " float3 eyevector = position * -1.0;\n"
2697 "# ifdef USEEXACTSPECULARMATH\n"
2698 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
2700 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2701 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
2705 "#if defined(USESHADOWMAP2D)\n"
2706 " fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2707 "#ifdef USESHADOWMAPVSDCT\n"
2708 ", Texture_CubeProjection\n"
2713 "#ifdef USEDIFFUSE\n"
2714 " gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2716 " gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2718 "#ifdef USESPECULAR\n"
2719 " gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2721 " gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2724 "# ifdef USECUBEFILTER\n"
2725 " float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2726 " gl_FragData0.rgb *= cubecolor;\n"
2727 " gl_FragData1.rgb *= cubecolor;\n"
2730 "#endif // FRAGMENT_SHADER\n"
2731 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2736 "#ifdef VERTEX_SHADER\n"
2739 "float4 gl_Vertex : POSITION,\n"
2740 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2741 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2742 "float4 gl_Color : COLOR0,\n"
2744 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2745 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2746 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2747 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2748 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2750 "uniform float3 EyePosition : register(c24),\n"
2751 "uniform float4x4 TexMatrix : register(c0),\n"
2752 "#ifdef USEVERTEXTEXTUREBLEND\n"
2753 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2755 "#ifdef MODE_LIGHTSOURCE\n"
2756 "uniform float4x4 ModelToLight : register(c20),\n"
2758 "#ifdef MODE_LIGHTSOURCE\n"
2759 "uniform float3 LightPosition : register(c27),\n"
2761 "#ifdef MODE_LIGHTDIRECTION\n"
2762 "uniform float3 LightDir : register(c26),\n"
2764 "uniform float4 FogPlane : register(c25),\n"
2765 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2766 "uniform float3 LightPosition : register(c27),\n"
2768 "#ifdef USESHADOWMAPORTHO\n"
2769 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2771 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2772 "out float4 gl_FrontColor : COLOR,\n"
2774 "out float4 TexCoordBoth : TEXCOORD0,\n"
2775 "#ifdef USELIGHTMAP\n"
2776 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2778 "#ifdef USEEYEVECTOR\n"
2779 "out float3 EyeVector : TEXCOORD2,\n"
2781 "#ifdef USEREFLECTION\n"
2782 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2785 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2787 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE) || defined(USEDIFFUSE)\n"
2788 "out float3 LightVector : TEXCOORD1,\n"
2790 "#ifdef MODE_LIGHTSOURCE\n"
2791 "out float3 CubeVector : TEXCOORD3,\n"
2793 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2794 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2795 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2796 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2798 "#ifdef USESHADOWMAPORTHO\n"
2799 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2801 "out float4 gl_Position : POSITION\n"
2804 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2806 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2808 " gl_FrontColor = gl_Color; // Cg is forward\n"
2811 " // copy the surface texcoord\n"
2812 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2813 "#ifdef USEVERTEXTEXTUREBLEND\n"
2814 " TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2816 "#ifdef USELIGHTMAP\n"
2817 " TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2820 "#ifdef MODE_LIGHTSOURCE\n"
2821 " // transform vertex position into light attenuation/cubemap space\n"
2822 " // (-1 to +1 across the light box)\n"
2823 " CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2825 "# ifdef USEDIFFUSE\n"
2826 " // transform unnormalized light direction into tangent space\n"
2827 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
2828 " // normalize it per pixel)\n"
2829 " float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2830 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2831 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2832 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2836 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2837 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2838 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2839 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2842 " // transform unnormalized eye direction into tangent space\n"
2843 "#ifdef USEEYEVECTOR\n"
2844 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2845 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2846 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2847 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2851 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2852 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2855 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2856 " VectorS = gl_MultiTexCoord1.xyz;\n"
2857 " VectorT = gl_MultiTexCoord2.xyz;\n"
2858 " VectorR = gl_MultiTexCoord3.xyz;\n"
2861 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2862 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2864 "#ifdef USESHADOWMAPORTHO\n"
2865 " ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2868 "#ifdef USEREFLECTION\n"
2869 " ModelViewProjectionPosition = gl_Position;\n"
2872 "#endif // VERTEX_SHADER\n"
2877 "#ifdef FRAGMENT_SHADER\n"
2880 "#ifdef USEDEFERREDLIGHTMAP\n"
2882 "float2 Pixel : VPOS,\n"
2884 "float2 Pixel : WPOS,\n"
2887 "float4 gl_FrontColor : COLOR,\n"
2888 "float4 TexCoordBoth : TEXCOORD0,\n"
2889 "#ifdef USELIGHTMAP\n"
2890 "float2 TexCoordLightmap : TEXCOORD1,\n"
2892 "#ifdef USEEYEVECTOR\n"
2893 "float3 EyeVector : TEXCOORD2,\n"
2895 "#ifdef USEREFLECTION\n"
2896 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2899 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2901 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2902 "float3 LightVector : TEXCOORD1,\n"
2904 "#ifdef MODE_LIGHTSOURCE\n"
2905 "float3 CubeVector : TEXCOORD3,\n"
2907 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2908 "float4 ModelViewPosition : TEXCOORD0,\n"
2910 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2911 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2912 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2913 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2915 "#ifdef USESHADOWMAPORTHO\n"
2916 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2919 "uniform sampler Texture_Normal : register(s0),\n"
2920 "uniform sampler Texture_Color : register(s1),\n"
2921 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2922 "uniform sampler Texture_Gloss : register(s2),\n"
2925 "uniform sampler Texture_Glow : register(s3),\n"
2927 "#ifdef USEVERTEXTEXTUREBLEND\n"
2928 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2929 "uniform sampler Texture_SecondaryColor : register(s5),\n"
2930 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2931 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2934 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
2937 "#ifdef USECOLORMAPPING\n"
2938 "uniform sampler Texture_Pants : register(s4),\n"
2939 "uniform sampler Texture_Shirt : register(s7),\n"
2942 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
2943 "uniform sampler Texture_FogMask : register(s8),\n"
2945 "#ifdef USELIGHTMAP\n"
2946 "uniform sampler Texture_Lightmap : register(s9),\n"
2948 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2949 "uniform sampler Texture_Deluxemap : register(s10),\n"
2951 "#ifdef USEREFLECTION\n"
2952 "uniform sampler Texture_Reflection : register(s7),\n"
2955 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2956 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2957 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2959 "#ifdef USEDEFERREDLIGHTMAP\n"
2960 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2961 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2962 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
2963 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
2966 "#ifdef USECOLORMAPPING\n"
2967 "uniform half3 Color_Pants : register(c7),\n"
2968 "uniform half3 Color_Shirt : register(c8),\n"
2971 "uniform float3 FogColor : register(c16),\n"
2972 "uniform float FogRangeRecip : register(c20),\n"
2973 "uniform float FogPlaneViewDist : register(c19),\n"
2974 "uniform float FogHeightFade : register(c17),\n"
2977 "#ifdef USEOFFSETMAPPING\n"
2978 "uniform float OffsetMapping_Scale : register(c24),\n"
2981 "#ifdef USEDEFERREDLIGHTMAP\n"
2982 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2983 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
2984 "uniform half3 DeferredMod_Specular : register(c13),\n"
2986 "uniform half3 Color_Ambient : register(c3),\n"
2987 "uniform half3 Color_Diffuse : register(c4),\n"
2988 "uniform half3 Color_Specular : register(c5),\n"
2989 "uniform half SpecularPower : register(c36),\n"
2991 "uniform half3 Color_Glow : register(c6),\n"
2993 "uniform half Alpha : register(c0),\n"
2994 "#ifdef USEREFLECTION\n"
2995 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2996 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2997 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2998 "uniform half4 ReflectColor : register(c26),\n"
3000 "#ifdef USEREFLECTCUBE\n"
3001 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3002 "uniform sampler Texture_ReflectMask : register(s5),\n"
3003 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3005 "#ifdef MODE_LIGHTDIRECTION\n"
3006 "uniform half3 LightColor : register(c21),\n"
3008 "#ifdef MODE_LIGHTSOURCE\n"
3009 "uniform half3 LightColor : register(c21),\n"
3012 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3013 "uniform sampler Texture_Attenuation : register(s9),\n"
3014 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3017 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3019 "#ifdef USESHADOWMAP2D\n"
3020 "# ifdef USESHADOWSAMPLER\n"
3021 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3023 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3027 "#ifdef USESHADOWMAPVSDCT\n"
3028 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3031 "#if defined(USESHADOWMAP2D)\n"
3032 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3033 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3035 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3037 "out float4 gl_FragColor : COLOR\n"
3040 " float2 TexCoord = TexCoordBoth.xy;\n"
3041 "#ifdef USEVERTEXTEXTUREBLEND\n"
3042 " float2 TexCoord2 = TexCoordBoth.zw;\n"
3044 "#ifdef USEOFFSETMAPPING\n"
3045 " // apply offsetmapping\n"
3046 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3047 "#define TexCoord TexCoordOffset\n"
3050 " // combine the diffuse textures (base, pants, shirt)\n"
3051 " half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3052 "#ifdef USEALPHAKILL\n"
3053 " if (color.a < 0.5)\n"
3056 " color.a *= Alpha;\n"
3057 "#ifdef USECOLORMAPPING\n"
3058 " color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3060 "#ifdef USEVERTEXTEXTUREBLEND\n"
3061 " half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3062 " //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3063 " //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3064 " color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3066 " //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3069 " // get the surface normal\n"
3070 "#ifdef USEVERTEXTEXTUREBLEND\n"
3071 " half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3073 " half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3076 " // get the material colors\n"
3077 " half3 diffusetex = color.rgb;\n"
3078 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3079 "# ifdef USEVERTEXTEXTUREBLEND\n"
3080 " half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3082 " half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3086 "#ifdef USEREFLECTCUBE\n"
3087 " float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3088 " float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3089 " float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3090 " diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3096 "#ifdef MODE_LIGHTSOURCE\n"
3097 " // light source\n"
3098 "#ifdef USEDIFFUSE\n"
3099 " half3 lightnormal = half3(normalize(LightVector));\n"
3100 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3101 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3102 "#ifdef USESPECULAR\n"
3103 "#ifdef USEEXACTSPECULARMATH\n"
3104 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3106 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3107 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3109 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3112 " color.rgb = diffusetex * Color_Ambient;\n"
3114 " color.rgb *= LightColor;\n"
3115 " color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3116 "#if defined(USESHADOWMAP2D)\n"
3117 " color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3118 "#ifdef USESHADOWMAPVSDCT\n"
3119 ", Texture_CubeProjection\n"
3124 "# ifdef USECUBEFILTER\n"
3125 " color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3128 "#ifdef USESHADOWMAP2D\n"
3129 "#ifdef USESHADOWMAPVSDCT\n"
3130 "// float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3132 "// float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3134 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3135 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3136 "// color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3137 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3138 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3139 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3140 "// color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3141 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3142 "// color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3143 "// color.r = half(shadowmaptc.z);\n"
3144 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3145 "// color.r = half(shadowmaptc.z);\n"
3147 "// color.rgb = abs(CubeVector);\n"
3149 "// color.rgb = half3(1,1,1);\n"
3150 "#endif // MODE_LIGHTSOURCE\n"
3155 "#ifdef MODE_LIGHTDIRECTION\n"
3157 "#ifdef USEDIFFUSE\n"
3158 " half3 lightnormal = half3(normalize(LightVector));\n"
3160 "#define lightcolor LightColor\n"
3161 "#endif // MODE_LIGHTDIRECTION\n"
3162 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3164 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3165 " half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3166 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3167 " // convert modelspace light vector to tangentspace\n"
3168 " half3 lightnormal;\n"
3169 " lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3170 " lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3171 " lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3172 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3173 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3174 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3175 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3176 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3177 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3178 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3179 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3180 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3181 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3182 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3183 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3185 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3186 " half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3187 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3193 "#ifdef MODE_FAKELIGHT\n"
3195 "half3 lightnormal = half3(normalize(EyeVector));\n"
3196 "half3 lightcolor = half3(1.0);\n"
3197 "#endif // MODE_FAKELIGHT\n"
3202 "#ifdef MODE_LIGHTMAP\n"
3203 " color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3204 "#endif // MODE_LIGHTMAP\n"
3205 "#ifdef MODE_VERTEXCOLOR\n"
3206 " color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3207 "#endif // MODE_VERTEXCOLOR\n"
3208 "#ifdef MODE_FLATCOLOR\n"
3209 " color.rgb = diffusetex * Color_Ambient;\n"
3210 "#endif // MODE_FLATCOLOR\n"
3216 "# ifdef USEDIFFUSE\n"
3217 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3218 "# ifdef USESPECULAR\n"
3219 "# ifdef USEEXACTSPECULARMATH\n"
3220 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3222 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3223 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3225 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3227 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3230 " color.rgb = diffusetex * Color_Ambient;\n"
3234 "#ifdef USESHADOWMAPORTHO\n"
3235 " color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
3238 "#ifdef USEDEFERREDLIGHTMAP\n"
3239 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3240 " color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3241 " color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3242 "// color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
3243 "// color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
3247 "#ifdef USEVERTEXTEXTUREBLEND\n"
3248 " color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3250 " color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3255 " color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3258 " // 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"
3259 "#ifdef USEREFLECTION\n"
3260 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3261 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3262 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3263 " float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3264 " // FIXME temporary hack to detect the case that the reflection\n"
3265 " // gets blackened at edges due to leaving the area that contains actual\n"
3267 " // Remove this 'ack once we have a better way to stop this thing from\n"
3269 " float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3270 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3271 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3272 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3273 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3274 " color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3277 " gl_FragColor = float4(color);\n"
3279 "#endif // FRAGMENT_SHADER\n"
3281 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3282 "#endif // !MODE_DEFERREDGEOMETRY\n"
3283 "#endif // !MODE_WATER\n"
3284 "#endif // !MODE_REFRACTION\n"
3285 "#endif // !MODE_BLOOMBLUR\n"
3286 "#endif // !MODE_GENERIC\n"
3287 "#endif // !MODE_POSTPROCESS\n"
3288 "#endif // !MODE_SHOWDEPTH\n"
3289 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3292 char *glslshaderstring = NULL;
3293 char *cgshaderstring = NULL;
3294 char *hlslshaderstring = NULL;
3296 //=======================================================================================================================================================
3298 typedef struct shaderpermutationinfo_s
3300 const char *pretext;
3303 shaderpermutationinfo_t;
3305 typedef struct shadermodeinfo_s
3307 const char *vertexfilename;
3308 const char *geometryfilename;
3309 const char *fragmentfilename;
3310 const char *pretext;
3315 typedef enum shaderpermutation_e
3317 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3318 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3319 SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3320 SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3321 SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3322 SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3323 SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3324 SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3325 SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3326 SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3327 SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3328 SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3329 SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3330 SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3331 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<14, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3332 SHADERPERMUTATION_REFLECTION = 1<<15, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3333 SHADERPERMUTATION_OFFSETMAPPING = 1<<16, ///< adjust texcoords to roughly simulate a displacement mapped surface
3334 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<17, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3335 SHADERPERMUTATION_SHADOWMAP2D = 1<<18, ///< (lightsource) use shadowmap texture as light filter
3336 SHADERPERMUTATION_SHADOWMAPPCF = 1<<19, ///< (lightsource) use percentage closer filtering on shadowmap test results
3337 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<20, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3338 SHADERPERMUTATION_SHADOWSAMPLER = 1<<21, ///< (lightsource) use hardware shadowmap test
3339 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<22, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3340 SHADERPERMUTATION_SHADOWMAPORTHO = 1<<23, //< (lightsource) use orthographic shadowmap projection
3341 SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3342 SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3343 SHADERPERMUTATION_REFLECTCUBE = 1<<26, ///< fake reflections using global cubemap (not HDRI light probe)
3344 SHADERPERMUTATION_NORMALMAPSCROLLBLEND = 1<<27, // (water) counter-direction normalmaps scrolling
3345 SHADERPERMUTATION_LIMIT = 1<<28, ///< size of permutations array
3346 SHADERPERMUTATION_COUNT = 28 ///< size of shaderpermutationinfo array
3348 shaderpermutation_t;
3350 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3351 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3353 {"#define USEDIFFUSE\n", " diffuse"},
3354 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3355 {"#define USEVIEWTINT\n", " viewtint"},
3356 {"#define USECOLORMAPPING\n", " colormapping"},
3357 {"#define USESATURATION\n", " saturation"},
3358 {"#define USEFOGINSIDE\n", " foginside"},
3359 {"#define USEFOGOUTSIDE\n", " fogoutside"},
3360 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3361 {"#define USEGAMMARAMPS\n", " gammaramps"},
3362 {"#define USECUBEFILTER\n", " cubefilter"},
3363 {"#define USEGLOW\n", " glow"},
3364 {"#define USEBLOOM\n", " bloom"},
3365 {"#define USESPECULAR\n", " specular"},
3366 {"#define USEPOSTPROCESSING\n", " postprocessing"},
3367 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3368 {"#define USEREFLECTION\n", " reflection"},
3369 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3370 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3371 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3372 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3373 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3374 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3375 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3376 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3377 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3378 {"#define USEALPHAKILL\n", " alphakill"},
3379 {"#define USEREFLECTCUBE\n", " reflectcube"},
3380 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
3383 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3384 typedef enum shadermode_e
3386 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3387 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3388 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3389 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3390 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3391 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3392 SHADERMODE_FAKELIGHT, ///< (fakelight) modulate texture by "fake" lighting (no lightmaps, no nothing)
3393 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3394 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3395 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3396 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3397 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3398 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3399 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3400 SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3401 SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3406 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3407 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3409 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3410 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3411 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3412 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3413 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3414 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3415 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3416 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3417 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3418 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3419 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3420 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3421 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3422 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3423 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3424 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3428 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3430 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3431 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3432 {"cg/default.cg", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3433 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3434 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3435 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3436 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FAKELIGHT\n", " fakelight"},
3437 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3438 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3439 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3440 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3441 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3442 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3443 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3444 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3445 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3450 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3452 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3453 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3454 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3455 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3456 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3457 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3458 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3459 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3460 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3461 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3462 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3463 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3464 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3465 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3466 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3470 struct r_glsl_permutation_s;
3471 typedef struct r_glsl_permutation_s
3473 /// hash lookup data
3474 struct r_glsl_permutation_s *hashnext;
3476 unsigned int permutation;
3478 /// indicates if we have tried compiling this permutation already
3480 /// 0 if compilation failed
3482 /// locations of detected uniforms in program object, or -1 if not found
3483 int loc_Texture_First;
3484 int loc_Texture_Second;
3485 int loc_Texture_GammaRamps;
3486 int loc_Texture_Normal;
3487 int loc_Texture_Color;
3488 int loc_Texture_Gloss;
3489 int loc_Texture_Glow;
3490 int loc_Texture_SecondaryNormal;
3491 int loc_Texture_SecondaryColor;
3492 int loc_Texture_SecondaryGloss;
3493 int loc_Texture_SecondaryGlow;
3494 int loc_Texture_Pants;
3495 int loc_Texture_Shirt;
3496 int loc_Texture_FogHeightTexture;
3497 int loc_Texture_FogMask;
3498 int loc_Texture_Lightmap;
3499 int loc_Texture_Deluxemap;
3500 int loc_Texture_Attenuation;
3501 int loc_Texture_Cube;
3502 int loc_Texture_Refraction;
3503 int loc_Texture_Reflection;
3504 int loc_Texture_ShadowMap2D;
3505 int loc_Texture_CubeProjection;
3506 int loc_Texture_ScreenDepth;
3507 int loc_Texture_ScreenNormalMap;
3508 int loc_Texture_ScreenDiffuse;
3509 int loc_Texture_ScreenSpecular;
3510 int loc_Texture_ReflectMask;
3511 int loc_Texture_ReflectCube;
3513 int loc_BloomBlur_Parameters;
3515 int loc_Color_Ambient;
3516 int loc_Color_Diffuse;
3517 int loc_Color_Specular;
3519 int loc_Color_Pants;
3520 int loc_Color_Shirt;
3521 int loc_DeferredColor_Ambient;
3522 int loc_DeferredColor_Diffuse;
3523 int loc_DeferredColor_Specular;
3524 int loc_DeferredMod_Diffuse;
3525 int loc_DeferredMod_Specular;
3526 int loc_DistortScaleRefractReflect;
3527 int loc_EyePosition;
3529 int loc_FogHeightFade;
3531 int loc_FogPlaneViewDist;
3532 int loc_FogRangeRecip;
3535 int loc_LightPosition;
3536 int loc_OffsetMapping_Scale;
3538 int loc_ReflectColor;
3539 int loc_ReflectFactor;
3540 int loc_ReflectOffset;
3541 int loc_RefractColor;
3543 int loc_ScreenCenterRefractReflect;
3544 int loc_ScreenScaleRefractReflect;
3545 int loc_ScreenToDepth;
3546 int loc_ShadowMap_Parameters;
3547 int loc_ShadowMap_TextureScale;
3548 int loc_SpecularPower;
3553 int loc_ViewTintColor;
3554 int loc_ViewToLight;
3555 int loc_ModelToLight;
3557 int loc_BackgroundTexMatrix;
3558 int loc_ModelViewProjectionMatrix;
3559 int loc_ModelViewMatrix;
3560 int loc_PixelToScreenTexCoord;
3561 int loc_ModelToReflectCube;
3562 int loc_ShadowMapMatrix;
3563 int loc_BloomColorSubtract;
3564 int loc_NormalmapScrollBlend;
3566 r_glsl_permutation_t;
3568 #define SHADERPERMUTATION_HASHSIZE 256
3570 /// information about each possible shader permutation
3571 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3572 /// currently selected permutation
3573 r_glsl_permutation_t *r_glsl_permutation;
3574 /// storage for permutations linked in the hash table
3575 memexpandablearray_t r_glsl_permutationarray;
3577 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3579 //unsigned int hashdepth = 0;
3580 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3581 r_glsl_permutation_t *p;
3582 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3584 if (p->mode == mode && p->permutation == permutation)
3586 //if (hashdepth > 10)
3587 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3592 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3594 p->permutation = permutation;
3595 p->hashnext = r_glsl_permutationhash[mode][hashindex];
3596 r_glsl_permutationhash[mode][hashindex] = p;
3597 //if (hashdepth > 10)
3598 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3602 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3605 if (!filename || !filename[0])
3607 if (!strcmp(filename, "glsl/default.glsl"))
3609 if (!glslshaderstring)
3611 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3612 if (glslshaderstring)
3613 Con_DPrintf("Loading shaders from file %s...\n", filename);
3615 glslshaderstring = (char *)builtinshaderstring;
3617 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3618 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3619 return shaderstring;
3621 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3624 if (printfromdisknotice)
3625 Con_DPrintf("from disk %s... ", filename);
3626 return shaderstring;
3628 return shaderstring;
3631 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3634 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3635 int vertstrings_count = 0;
3636 int geomstrings_count = 0;
3637 int fragstrings_count = 0;
3638 char *vertexstring, *geometrystring, *fragmentstring;
3639 const char *vertstrings_list[32+3];
3640 const char *geomstrings_list[32+3];
3641 const char *fragstrings_list[32+3];
3642 char permutationname[256];
3649 permutationname[0] = 0;
3650 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
3651 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3652 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3654 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3656 // the first pretext is which type of shader to compile as
3657 // (later these will all be bound together as a program object)
3658 vertstrings_count = 0;
3659 geomstrings_count = 0;
3660 fragstrings_count = 0;
3661 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3662 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3663 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3665 // the second pretext is the mode (for example a light source)
3666 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3667 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3668 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3669 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3671 // now add all the permutation pretexts
3672 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3674 if (permutation & (1<<i))
3676 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3677 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3678 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3679 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3683 // keep line numbers correct
3684 vertstrings_list[vertstrings_count++] = "\n";
3685 geomstrings_list[geomstrings_count++] = "\n";
3686 fragstrings_list[fragstrings_count++] = "\n";
3690 // now append the shader text itself
3691 vertstrings_list[vertstrings_count++] = vertexstring;
3692 geomstrings_list[geomstrings_count++] = geometrystring;
3693 fragstrings_list[fragstrings_count++] = fragmentstring;
3695 // if any sources were NULL, clear the respective list
3697 vertstrings_count = 0;
3698 if (!geometrystring)
3699 geomstrings_count = 0;
3700 if (!fragmentstring)
3701 fragstrings_count = 0;
3703 // compile the shader program
3704 if (vertstrings_count + geomstrings_count + fragstrings_count)
3705 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3709 qglUseProgramObjectARB(p->program);CHECKGLERROR
3710 // look up all the uniform variable names we care about, so we don't
3711 // have to look them up every time we set them
3713 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
3714 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
3715 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3716 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
3717 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
3718 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3719 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
3720 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3721 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3722 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3723 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3724 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
3725 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3726 p->loc_Texture_FogHeightTexture = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3727 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3728 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3729 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3730 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3731 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
3732 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3733 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3734 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3735 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3736 p->loc_Texture_ScreenDepth = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3737 p->loc_Texture_ScreenNormalMap = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3738 p->loc_Texture_ScreenDiffuse = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3739 p->loc_Texture_ScreenSpecular = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3740 p->loc_Texture_ReflectMask = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3741 p->loc_Texture_ReflectCube = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3742 p->loc_Alpha = qglGetUniformLocationARB(p->program, "Alpha");
3743 p->loc_BloomBlur_Parameters = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3744 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
3745 p->loc_Color_Ambient = qglGetUniformLocationARB(p->program, "Color_Ambient");
3746 p->loc_Color_Diffuse = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3747 p->loc_Color_Specular = qglGetUniformLocationARB(p->program, "Color_Specular");
3748 p->loc_Color_Glow = qglGetUniformLocationARB(p->program, "Color_Glow");
3749 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
3750 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
3751 p->loc_DeferredColor_Ambient = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3752 p->loc_DeferredColor_Diffuse = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3753 p->loc_DeferredColor_Specular = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3754 p->loc_DeferredMod_Diffuse = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3755 p->loc_DeferredMod_Specular = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3756 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3757 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
3758 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
3759 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
3760 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
3761 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3762 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3763 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
3764 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
3765 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
3766 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3767 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
3768 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
3769 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
3770 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
3771 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
3772 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
3773 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3774 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3775 p->loc_ScreenToDepth = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3776 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3777 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3778 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
3779 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
3780 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
3781 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
3782 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
3783 p->loc_ViewTintColor = qglGetUniformLocationARB(p->program, "ViewTintColor");
3784 p->loc_ViewToLight = qglGetUniformLocationARB(p->program, "ViewToLight");
3785 p->loc_ModelToLight = qglGetUniformLocationARB(p->program, "ModelToLight");
3786 p->loc_TexMatrix = qglGetUniformLocationARB(p->program, "TexMatrix");
3787 p->loc_BackgroundTexMatrix = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3788 p->loc_ModelViewMatrix = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3789 p->loc_ModelViewProjectionMatrix = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3790 p->loc_PixelToScreenTexCoord = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3791 p->loc_ModelToReflectCube = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3792 p->loc_ShadowMapMatrix = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3793 p->loc_BloomColorSubtract = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
3794 p->loc_NormalmapScrollBlend = qglGetUniformLocationARB(p->program, "NormalmapScrollBlend");
3795 // initialize the samplers to refer to the texture units we use
3796 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
3797 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
3798 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
3799 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
3800 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
3801 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
3802 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
3803 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3804 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3805 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3806 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
3807 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
3808 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
3809 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3810 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
3811 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
3812 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
3813 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
3814 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
3815 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
3816 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
3817 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
3818 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3819 if (p->loc_Texture_ScreenDepth >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth , GL20TU_SCREENDEPTH);
3820 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3821 if (p->loc_Texture_ScreenDiffuse >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse , GL20TU_SCREENDIFFUSE);
3822 if (p->loc_Texture_ScreenSpecular >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3823 if (p->loc_Texture_ReflectMask >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask , GL20TU_REFLECTMASK);
3824 if (p->loc_Texture_ReflectCube >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube , GL20TU_REFLECTCUBE);
3826 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3829 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
3833 Mem_Free(vertexstring);
3835 Mem_Free(geometrystring);
3837 Mem_Free(fragmentstring);
3840 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3842 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3843 if (r_glsl_permutation != perm)
3845 r_glsl_permutation = perm;
3846 if (!r_glsl_permutation->program)
3848 if (!r_glsl_permutation->compiled)
3849 R_GLSL_CompilePermutation(perm, mode, permutation);
3850 if (!r_glsl_permutation->program)
3852 // remove features until we find a valid permutation
3854 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3856 // reduce i more quickly whenever it would not remove any bits
3857 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3858 if (!(permutation & j))
3861 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3862 if (!r_glsl_permutation->compiled)
3863 R_GLSL_CompilePermutation(perm, mode, permutation);
3864 if (r_glsl_permutation->program)
3867 if (i >= SHADERPERMUTATION_COUNT)
3869 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3870 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3871 qglUseProgramObjectARB(0);CHECKGLERROR
3872 return; // no bit left to clear, entire mode is broken
3877 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3879 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3880 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3881 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3885 #include <Cg/cgGL.h>
3886 struct r_cg_permutation_s;
3887 typedef struct r_cg_permutation_s
3889 /// hash lookup data
3890 struct r_cg_permutation_s *hashnext;
3892 unsigned int permutation;
3894 /// indicates if we have tried compiling this permutation already
3896 /// 0 if compilation failed
3899 /// locations of detected parameters in programs, or NULL if not found
3900 CGparameter vp_EyePosition;
3901 CGparameter vp_FogPlane;
3902 CGparameter vp_LightDir;
3903 CGparameter vp_LightPosition;
3904 CGparameter vp_ModelToLight;
3905 CGparameter vp_TexMatrix;
3906 CGparameter vp_BackgroundTexMatrix;
3907 CGparameter vp_ModelViewProjectionMatrix;
3908 CGparameter vp_ModelViewMatrix;
3909 CGparameter vp_ShadowMapMatrix;
3911 CGparameter fp_Texture_First;
3912 CGparameter fp_Texture_Second;
3913 CGparameter fp_Texture_GammaRamps;
3914 CGparameter fp_Texture_Normal;
3915 CGparameter fp_Texture_Color;
3916 CGparameter fp_Texture_Gloss;
3917 CGparameter fp_Texture_Glow;
3918 CGparameter fp_Texture_SecondaryNormal;
3919 CGparameter fp_Texture_SecondaryColor;
3920 CGparameter fp_Texture_SecondaryGloss;
3921 CGparameter fp_Texture_SecondaryGlow;
3922 CGparameter fp_Texture_Pants;
3923 CGparameter fp_Texture_Shirt;
3924 CGparameter fp_Texture_FogHeightTexture;
3925 CGparameter fp_Texture_FogMask;
3926 CGparameter fp_Texture_Lightmap;
3927 CGparameter fp_Texture_Deluxemap;
3928 CGparameter fp_Texture_Attenuation;
3929 CGparameter fp_Texture_Cube;
3930 CGparameter fp_Texture_Refraction;
3931 CGparameter fp_Texture_Reflection;
3932 CGparameter fp_Texture_ShadowMap2D;
3933 CGparameter fp_Texture_CubeProjection;
3934 CGparameter fp_Texture_ScreenDepth;
3935 CGparameter fp_Texture_ScreenNormalMap;
3936 CGparameter fp_Texture_ScreenDiffuse;
3937 CGparameter fp_Texture_ScreenSpecular;
3938 CGparameter fp_Texture_ReflectMask;
3939 CGparameter fp_Texture_ReflectCube;
3940 CGparameter fp_Alpha;
3941 CGparameter fp_BloomBlur_Parameters;
3942 CGparameter fp_ClientTime;
3943 CGparameter fp_Color_Ambient;
3944 CGparameter fp_Color_Diffuse;
3945 CGparameter fp_Color_Specular;
3946 CGparameter fp_Color_Glow;
3947 CGparameter fp_Color_Pants;
3948 CGparameter fp_Color_Shirt;
3949 CGparameter fp_DeferredColor_Ambient;
3950 CGparameter fp_DeferredColor_Diffuse;
3951 CGparameter fp_DeferredColor_Specular;
3952 CGparameter fp_DeferredMod_Diffuse;
3953 CGparameter fp_DeferredMod_Specular;
3954 CGparameter fp_DistortScaleRefractReflect;
3955 CGparameter fp_EyePosition;
3956 CGparameter fp_FogColor;
3957 CGparameter fp_FogHeightFade;
3958 CGparameter fp_FogPlane;
3959 CGparameter fp_FogPlaneViewDist;
3960 CGparameter fp_FogRangeRecip;
3961 CGparameter fp_LightColor;
3962 CGparameter fp_LightDir;
3963 CGparameter fp_LightPosition;
3964 CGparameter fp_OffsetMapping_Scale;
3965 CGparameter fp_PixelSize;
3966 CGparameter fp_ReflectColor;
3967 CGparameter fp_ReflectFactor;
3968 CGparameter fp_ReflectOffset;
3969 CGparameter fp_RefractColor;
3970 CGparameter fp_Saturation;
3971 CGparameter fp_ScreenCenterRefractReflect;
3972 CGparameter fp_ScreenScaleRefractReflect;
3973 CGparameter fp_ScreenToDepth;
3974 CGparameter fp_ShadowMap_Parameters;
3975 CGparameter fp_ShadowMap_TextureScale;
3976 CGparameter fp_SpecularPower;
3977 CGparameter fp_UserVec1;
3978 CGparameter fp_UserVec2;
3979 CGparameter fp_UserVec3;
3980 CGparameter fp_UserVec4;
3981 CGparameter fp_ViewTintColor;
3982 CGparameter fp_ViewToLight;
3983 CGparameter fp_PixelToScreenTexCoord;
3984 CGparameter fp_ModelToReflectCube;
3985 CGparameter fp_BloomColorSubtract;
3986 CGparameter fp_NormalmapScrollBlend;
3990 /// information about each possible shader permutation
3991 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3992 /// currently selected permutation
3993 r_cg_permutation_t *r_cg_permutation;
3994 /// storage for permutations linked in the hash table
3995 memexpandablearray_t r_cg_permutationarray;
3997 #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));}}
3999 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
4001 //unsigned int hashdepth = 0;
4002 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4003 r_cg_permutation_t *p;
4004 for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4006 if (p->mode == mode && p->permutation == permutation)
4008 //if (hashdepth > 10)
4009 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4014 p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4016 p->permutation = permutation;
4017 p->hashnext = r_cg_permutationhash[mode][hashindex];
4018 r_cg_permutationhash[mode][hashindex] = p;
4019 //if (hashdepth > 10)
4020 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4024 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4027 if (!filename || !filename[0])
4029 if (!strcmp(filename, "cg/default.cg"))
4031 if (!cgshaderstring)
4033 cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4035 Con_DPrintf("Loading shaders from file %s...\n", filename);
4037 cgshaderstring = (char *)builtincgshaderstring;
4039 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4040 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4041 return shaderstring;
4043 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4046 if (printfromdisknotice)
4047 Con_DPrintf("from disk %s... ", filename);
4048 return shaderstring;
4050 return shaderstring;
4053 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4055 // TODO: load or create .fp and .vp shader files
4058 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4061 shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4062 int vertstrings_count = 0, vertstring_length = 0;
4063 int geomstrings_count = 0, geomstring_length = 0;
4064 int fragstrings_count = 0, fragstring_length = 0;
4065 char *vertexstring, *geometrystring, *fragmentstring;
4066 const char *vertstrings_list[32+3];
4067 const char *geomstrings_list[32+3];
4068 const char *fragstrings_list[32+3];
4069 char *vertstring, *geomstring, *fragstring;
4070 char permutationname[256];
4071 char cachename[256];
4072 CGprofile vertexProfile;
4073 CGprofile fragmentProfile;
4081 permutationname[0] = 0;
4083 vertexstring = R_CG_GetText(modeinfo->vertexfilename, true);
4084 geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4085 fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4087 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4088 strlcat(cachename, "cg/", sizeof(cachename));
4090 // the first pretext is which type of shader to compile as
4091 // (later these will all be bound together as a program object)
4092 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4093 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4094 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4096 // the second pretext is the mode (for example a light source)
4097 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4098 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4099 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4100 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4101 strlcat(cachename, modeinfo->name, sizeof(cachename));
4103 // now add all the permutation pretexts
4104 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4106 if (permutation & (1<<i))
4108 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4109 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4110 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4111 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4112 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4116 // keep line numbers correct
4117 vertstrings_list[vertstrings_count++] = "\n";
4118 geomstrings_list[geomstrings_count++] = "\n";
4119 fragstrings_list[fragstrings_count++] = "\n";
4124 R_CompileShader_AddStaticParms(mode, permutation);
4126 // replace spaces in the cachename with _ characters
4127 for (i = 0;cachename[i];i++)
4128 if (cachename[i] == ' ')
4131 // now append the shader text itself
4132 vertstrings_list[vertstrings_count++] = vertexstring;
4133 geomstrings_list[geomstrings_count++] = geometrystring;
4134 fragstrings_list[fragstrings_count++] = fragmentstring;
4136 // if any sources were NULL, clear the respective list
4138 vertstrings_count = 0;
4139 if (!geometrystring)
4140 geomstrings_count = 0;
4141 if (!fragmentstring)
4142 fragstrings_count = 0;
4144 vertstring_length = 0;
4145 for (i = 0;i < vertstrings_count;i++)
4146 vertstring_length += strlen(vertstrings_list[i]);
4147 vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4148 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4149 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4151 geomstring_length = 0;
4152 for (i = 0;i < geomstrings_count;i++)
4153 geomstring_length += strlen(geomstrings_list[i]);
4154 geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4155 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4156 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4158 fragstring_length = 0;
4159 for (i = 0;i < fragstrings_count;i++)
4160 fragstring_length += strlen(fragstrings_list[i]);
4161 fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4162 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4163 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4167 //vertexProfile = CG_PROFILE_ARBVP1;
4168 //fragmentProfile = CG_PROFILE_ARBFP1;
4169 vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4170 fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4171 //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4172 //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4173 //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4176 // try to load the cached shader, or generate one
4177 R_CG_CacheShader(p, cachename, vertstring, fragstring);
4179 // if caching failed, do a dynamic compile for now
4181 if (vertstring[0] && !p->vprogram)
4182 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4184 if (fragstring[0] && !p->fprogram)
4185 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4188 // look up all the uniform variable names we care about, so we don't
4189 // have to look them up every time we set them
4193 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4194 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4195 p->vp_EyePosition = cgGetNamedParameter(p->vprogram, "EyePosition");
4196 p->vp_FogPlane = cgGetNamedParameter(p->vprogram, "FogPlane");
4197 p->vp_LightDir = cgGetNamedParameter(p->vprogram, "LightDir");
4198 p->vp_LightPosition = cgGetNamedParameter(p->vprogram, "LightPosition");
4199 p->vp_ModelToLight = cgGetNamedParameter(p->vprogram, "ModelToLight");
4200 p->vp_TexMatrix = cgGetNamedParameter(p->vprogram, "TexMatrix");
4201 p->vp_BackgroundTexMatrix = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4202 p->vp_ModelViewProjectionMatrix = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4203 p->vp_ModelViewMatrix = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4204 p->vp_ShadowMapMatrix = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4210 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4211 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4212 p->fp_Texture_First = cgGetNamedParameter(p->fprogram, "Texture_First");
4213 p->fp_Texture_Second = cgGetNamedParameter(p->fprogram, "Texture_Second");
4214 p->fp_Texture_GammaRamps = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4215 p->fp_Texture_Normal = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4216 p->fp_Texture_Color = cgGetNamedParameter(p->fprogram, "Texture_Color");
4217 p->fp_Texture_Gloss = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4218 p->fp_Texture_Glow = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4219 p->fp_Texture_SecondaryNormal = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4220 p->fp_Texture_SecondaryColor = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4221 p->fp_Texture_SecondaryGloss = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4222 p->fp_Texture_SecondaryGlow = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4223 p->fp_Texture_Pants = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4224 p->fp_Texture_Shirt = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4225 p->fp_Texture_FogHeightTexture = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4226 p->fp_Texture_FogMask = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4227 p->fp_Texture_Lightmap = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4228 p->fp_Texture_Deluxemap = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4229 p->fp_Texture_Attenuation = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4230 p->fp_Texture_Cube = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4231 p->fp_Texture_Refraction = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4232 p->fp_Texture_Reflection = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4233 p->fp_Texture_ShadowMap2D = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4234 p->fp_Texture_CubeProjection = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4235 p->fp_Texture_ScreenDepth = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4236 p->fp_Texture_ScreenNormalMap = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4237 p->fp_Texture_ScreenDiffuse = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4238 p->fp_Texture_ScreenSpecular = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4239 p->fp_Texture_ReflectMask = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4240 p->fp_Texture_ReflectCube = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4241 p->fp_Alpha = cgGetNamedParameter(p->fprogram, "Alpha");
4242 p->fp_BloomBlur_Parameters = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4243 p->fp_ClientTime = cgGetNamedParameter(p->fprogram, "ClientTime");
4244 p->fp_Color_Ambient = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4245 p->fp_Color_Diffuse = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4246 p->fp_Color_Specular = cgGetNamedParameter(p->fprogram, "Color_Specular");
4247 p->fp_Color_Glow = cgGetNamedParameter(p->fprogram, "Color_Glow");
4248 p->fp_Color_Pants = cgGetNamedParameter(p->fprogram, "Color_Pants");
4249 p->fp_Color_Shirt = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4250 p->fp_DeferredColor_Ambient = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4251 p->fp_DeferredColor_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4252 p->fp_DeferredColor_Specular = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4253 p->fp_DeferredMod_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4254 p->fp_DeferredMod_Specular = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4255 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4256 p->fp_EyePosition = cgGetNamedParameter(p->fprogram, "EyePosition");
4257 p->fp_FogColor = cgGetNamedParameter(p->fprogram, "FogColor");
4258 p->fp_FogHeightFade = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4259 p->fp_FogPlane = cgGetNamedParameter(p->fprogram, "FogPlane");
4260 p->fp_FogPlaneViewDist = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4261 p->fp_FogRangeRecip = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4262 p->fp_LightColor = cgGetNamedParameter(p->fprogram, "LightColor");
4263 p->fp_LightDir = cgGetNamedParameter(p->fprogram, "LightDir");
4264 p->fp_LightPosition = cgGetNamedParameter(p->fprogram, "LightPosition");
4265 p->fp_OffsetMapping_Scale = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4266 p->fp_PixelSize = cgGetNamedParameter(p->fprogram, "PixelSize");
4267 p->fp_ReflectColor = cgGetNamedParameter(p->fprogram, "ReflectColor");
4268 p->fp_ReflectFactor = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4269 p->fp_ReflectOffset = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4270 p->fp_RefractColor = cgGetNamedParameter(p->fprogram, "RefractColor");
4271 p->fp_Saturation = cgGetNamedParameter(p->fprogram, "Saturation");
4272 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4273 p->fp_ScreenScaleRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4274 p->fp_ScreenToDepth = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4275 p->fp_ShadowMap_Parameters = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4276 p->fp_ShadowMap_TextureScale = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4277 p->fp_SpecularPower = cgGetNamedParameter(p->fprogram, "SpecularPower");
4278 p->fp_UserVec1 = cgGetNamedParameter(p->fprogram, "UserVec1");
4279 p->fp_UserVec2 = cgGetNamedParameter(p->fprogram, "UserVec2");
4280 p->fp_UserVec3 = cgGetNamedParameter(p->fprogram, "UserVec3");
4281 p->fp_UserVec4 = cgGetNamedParameter(p->fprogram, "UserVec4");
4282 p->fp_ViewTintColor = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4283 p->fp_ViewToLight = cgGetNamedParameter(p->fprogram, "ViewToLight");
4284 p->fp_PixelToScreenTexCoord = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4285 p->fp_ModelToReflectCube = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4286 p->fp_BloomColorSubtract = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4287 p->fp_NormalmapScrollBlend = cgGetNamedParameter(p->fprogram, "NormalmapScrollBlend");
4291 if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4292 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4294 Con_Printf("^1CG shader %s failed! some features may not work properly.\n", permutationname);
4298 Mem_Free(vertstring);
4300 Mem_Free(geomstring);
4302 Mem_Free(fragstring);
4304 Mem_Free(vertexstring);
4306 Mem_Free(geometrystring);
4308 Mem_Free(fragmentstring);
4311 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4313 r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4316 if (r_cg_permutation != perm)
4318 r_cg_permutation = perm;
4319 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4321 if (!r_cg_permutation->compiled)
4322 R_CG_CompilePermutation(perm, mode, permutation);
4323 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4325 // remove features until we find a valid permutation
4327 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4329 // reduce i more quickly whenever it would not remove any bits
4330 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4331 if (!(permutation & j))
4334 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4335 if (!r_cg_permutation->compiled)
4336 R_CG_CompilePermutation(perm, mode, permutation);
4337 if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4340 if (i >= SHADERPERMUTATION_COUNT)
4342 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4343 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4344 return; // no bit left to clear, entire mode is broken
4350 if (r_cg_permutation->vprogram)
4352 cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4353 cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4354 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4358 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4359 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4361 if (r_cg_permutation->fprogram)
4363 cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4364 cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4365 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4369 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4370 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4374 if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4375 if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4376 if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4379 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4381 cgGLSetTextureParameter(param, R_GetTexture(tex));
4382 cgGLEnableTextureParameter(param);
4390 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4391 extern D3DCAPS9 vid_d3d9caps;
4394 struct r_hlsl_permutation_s;
4395 typedef struct r_hlsl_permutation_s
4397 /// hash lookup data
4398 struct r_hlsl_permutation_s *hashnext;
4400 unsigned int permutation;
4402 /// indicates if we have tried compiling this permutation already
4404 /// NULL if compilation failed
4405 IDirect3DVertexShader9 *vertexshader;
4406 IDirect3DPixelShader9 *pixelshader;
4408 r_hlsl_permutation_t;
4410 typedef enum D3DVSREGISTER_e
4412 D3DVSREGISTER_TexMatrix = 0, // float4x4
4413 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4414 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4415 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4416 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4417 D3DVSREGISTER_ModelToLight = 20, // float4x4
4418 D3DVSREGISTER_EyePosition = 24,
4419 D3DVSREGISTER_FogPlane = 25,
4420 D3DVSREGISTER_LightDir = 26,
4421 D3DVSREGISTER_LightPosition = 27,
4425 typedef enum D3DPSREGISTER_e
4427 D3DPSREGISTER_Alpha = 0,
4428 D3DPSREGISTER_BloomBlur_Parameters = 1,
4429 D3DPSREGISTER_ClientTime = 2,
4430 D3DPSREGISTER_Color_Ambient = 3,
4431 D3DPSREGISTER_Color_Diffuse = 4,
4432 D3DPSREGISTER_Color_Specular = 5,
4433 D3DPSREGISTER_Color_Glow = 6,
4434 D3DPSREGISTER_Color_Pants = 7,
4435 D3DPSREGISTER_Color_Shirt = 8,
4436 D3DPSREGISTER_DeferredColor_Ambient = 9,
4437 D3DPSREGISTER_DeferredColor_Diffuse = 10,
4438 D3DPSREGISTER_DeferredColor_Specular = 11,
4439 D3DPSREGISTER_DeferredMod_Diffuse = 12,
4440 D3DPSREGISTER_DeferredMod_Specular = 13,
4441 D3DPSREGISTER_DistortScaleRefractReflect = 14,
4442 D3DPSREGISTER_EyePosition = 15, // unused
4443 D3DPSREGISTER_FogColor = 16,
4444 D3DPSREGISTER_FogHeightFade = 17,
4445 D3DPSREGISTER_FogPlane = 18,
4446 D3DPSREGISTER_FogPlaneViewDist = 19,
4447 D3DPSREGISTER_FogRangeRecip = 20,
4448 D3DPSREGISTER_LightColor = 21,
4449 D3DPSREGISTER_LightDir = 22, // unused
4450 D3DPSREGISTER_LightPosition = 23,
4451 D3DPSREGISTER_OffsetMapping_Scale = 24,
4452 D3DPSREGISTER_PixelSize = 25,
4453 D3DPSREGISTER_ReflectColor = 26,
4454 D3DPSREGISTER_ReflectFactor = 27,
4455 D3DPSREGISTER_ReflectOffset = 28,
4456 D3DPSREGISTER_RefractColor = 29,
4457 D3DPSREGISTER_Saturation = 30,
4458 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4459 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4460 D3DPSREGISTER_ScreenToDepth = 33,
4461 D3DPSREGISTER_ShadowMap_Parameters = 34,
4462 D3DPSREGISTER_ShadowMap_TextureScale = 35,
4463 D3DPSREGISTER_SpecularPower = 36,
4464 D3DPSREGISTER_UserVec1 = 37,
4465 D3DPSREGISTER_UserVec2 = 38,
4466 D3DPSREGISTER_UserVec3 = 39,
4467 D3DPSREGISTER_UserVec4 = 40,
4468 D3DPSREGISTER_ViewTintColor = 41,
4469 D3DPSREGISTER_PixelToScreenTexCoord = 42,
4470 D3DPSREGISTER_BloomColorSubtract = 43,
4471 D3DPSREGISTER_ViewToLight = 44, // float4x4
4472 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4473 D3DPSREGISTER_NormalmapScrollBlend = 52,
4478 /// information about each possible shader permutation
4479 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4480 /// currently selected permutation
4481 r_hlsl_permutation_t *r_hlsl_permutation;
4482 /// storage for permutations linked in the hash table
4483 memexpandablearray_t r_hlsl_permutationarray;
4485 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4487 //unsigned int hashdepth = 0;
4488 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4489 r_hlsl_permutation_t *p;
4490 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4492 if (p->mode == mode && p->permutation == permutation)
4494 //if (hashdepth > 10)
4495 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4500 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4502 p->permutation = permutation;
4503 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4504 r_hlsl_permutationhash[mode][hashindex] = p;
4505 //if (hashdepth > 10)
4506 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4510 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4513 if (!filename || !filename[0])
4515 if (!strcmp(filename, "hlsl/default.hlsl"))
4517 if (!hlslshaderstring)
4519 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4520 if (hlslshaderstring)
4521 Con_DPrintf("Loading shaders from file %s...\n", filename);
4523 hlslshaderstring = (char *)builtincgshaderstring;
4525 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4526 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4527 return shaderstring;
4529 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4532 if (printfromdisknotice)
4533 Con_DPrintf("from disk %s... ", filename);
4534 return shaderstring;
4536 return shaderstring;
4540 //#include <d3dx9shader.h>
4541 //#include <d3dx9mesh.h>
4543 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4545 DWORD *vsbin = NULL;
4546 DWORD *psbin = NULL;
4547 fs_offset_t vsbinsize;
4548 fs_offset_t psbinsize;
4549 // IDirect3DVertexShader9 *vs = NULL;
4550 // IDirect3DPixelShader9 *ps = NULL;
4551 ID3DXBuffer *vslog = NULL;
4552 ID3DXBuffer *vsbuffer = NULL;
4553 ID3DXConstantTable *vsconstanttable = NULL;
4554 ID3DXBuffer *pslog = NULL;
4555 ID3DXBuffer *psbuffer = NULL;
4556 ID3DXConstantTable *psconstanttable = NULL;
4559 char temp[MAX_INPUTLINE];
4560 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4561 qboolean debugshader = gl_paranoid.integer != 0;
4562 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4563 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4566 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4567 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4569 if ((!vsbin && vertstring) || (!psbin && fragstring))
4571 const char* dllnames_d3dx9 [] =
4595 dllhandle_t d3dx9_dll = NULL;
4596 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4597 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4598 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4599 dllfunction_t d3dx9_dllfuncs[] =
4601 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
4602 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
4603 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
4606 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4608 DWORD shaderflags = 0;
4610 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4611 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4612 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4613 if (vertstring && vertstring[0])
4617 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4618 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4619 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4620 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4623 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4626 vsbinsize = vsbuffer->GetBufferSize();
4627 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4628 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4629 vsbuffer->Release();
4633 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4634 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4638 if (fragstring && fragstring[0])
4642 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4643 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4644 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4645 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4648 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4651 psbinsize = psbuffer->GetBufferSize();
4652 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4653 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4654 psbuffer->Release();
4658 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4659 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4663 Sys_UnloadLibrary(&d3dx9_dll);
4666 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4670 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4671 if (FAILED(vsresult))
4672 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4673 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4674 if (FAILED(psresult))
4675 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4677 // free the shader data
4678 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4679 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4682 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4685 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4686 int vertstrings_count = 0, vertstring_length = 0;
4687 int geomstrings_count = 0, geomstring_length = 0;
4688 int fragstrings_count = 0, fragstring_length = 0;
4690 char *vertexstring, *geometrystring, *fragmentstring;
4691 const char *vertstrings_list[32+3];
4692 const char *geomstrings_list[32+3];
4693 const char *fragstrings_list[32+3];
4694 char *vertstring, *geomstring, *fragstring;
4695 char permutationname[256];
4696 char cachename[256];
4701 p->vertexshader = NULL;
4702 p->pixelshader = NULL;
4704 permutationname[0] = 0;
4706 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
4707 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4708 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4710 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4711 strlcat(cachename, "hlsl/", sizeof(cachename));
4713 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4714 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4715 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4716 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4718 // the first pretext is which type of shader to compile as
4719 // (later these will all be bound together as a program object)
4720 vertstrings_count = 0;
4721 geomstrings_count = 0;
4722 fragstrings_count = 0;
4723 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4724 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4725 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4727 // the second pretext is the mode (for example a light source)
4728 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4729 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4730 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4731 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4732 strlcat(cachename, modeinfo->name, sizeof(cachename));
4734 // now add all the permutation pretexts
4735 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4737 if (permutation & (1<<i))
4739 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4740 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4741 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4742 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4743 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4747 // keep line numbers correct
4748 vertstrings_list[vertstrings_count++] = "\n";
4749 geomstrings_list[geomstrings_count++] = "\n";
4750 fragstrings_list[fragstrings_count++] = "\n";
4754 // replace spaces in the cachename with _ characters
4755 for (i = 0;cachename[i];i++)
4756 if (cachename[i] == ' ')
4759 // now append the shader text itself
4760 vertstrings_list[vertstrings_count++] = vertexstring;
4761 geomstrings_list[geomstrings_count++] = geometrystring;
4762 fragstrings_list[fragstrings_count++] = fragmentstring;
4764 // if any sources were NULL, clear the respective list
4766 vertstrings_count = 0;
4767 if (!geometrystring)
4768 geomstrings_count = 0;
4769 if (!fragmentstring)
4770 fragstrings_count = 0;
4772 vertstring_length = 0;
4773 for (i = 0;i < vertstrings_count;i++)
4774 vertstring_length += strlen(vertstrings_list[i]);
4775 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4776 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4777 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4779 geomstring_length = 0;
4780 for (i = 0;i < geomstrings_count;i++)
4781 geomstring_length += strlen(geomstrings_list[i]);
4782 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4783 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4784 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4786 fragstring_length = 0;
4787 for (i = 0;i < fragstrings_count;i++)
4788 fragstring_length += strlen(fragstrings_list[i]);
4789 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4790 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4791 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4793 // try to load the cached shader, or generate one
4794 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4796 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4797 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4799 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
4803 Mem_Free(vertstring);
4805 Mem_Free(geomstring);
4807 Mem_Free(fragstring);
4809 Mem_Free(vertexstring);
4811 Mem_Free(geometrystring);
4813 Mem_Free(fragmentstring);
4816 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4817 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4818 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4819 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4820 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4821 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4823 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4824 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4825 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4826 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4827 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4828 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4830 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4832 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4833 if (r_hlsl_permutation != perm)
4835 r_hlsl_permutation = perm;
4836 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4838 if (!r_hlsl_permutation->compiled)
4839 R_HLSL_CompilePermutation(perm, mode, permutation);
4840 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4842 // remove features until we find a valid permutation
4844 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4846 // reduce i more quickly whenever it would not remove any bits
4847 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4848 if (!(permutation & j))
4851 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4852 if (!r_hlsl_permutation->compiled)
4853 R_HLSL_CompilePermutation(perm, mode, permutation);
4854 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4857 if (i >= SHADERPERMUTATION_COUNT)
4859 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4860 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4861 return; // no bit left to clear, entire mode is broken
4865 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4866 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4868 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4869 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4870 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4874 void R_GLSL_Restart_f(void)
4876 unsigned int i, limit;
4877 if (glslshaderstring && glslshaderstring != builtinshaderstring)
4878 Mem_Free(glslshaderstring);
4879 glslshaderstring = NULL;
4880 if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4881 Mem_Free(cgshaderstring);
4882 cgshaderstring = NULL;
4883 if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
4884 Mem_Free(hlslshaderstring);
4885 hlslshaderstring = NULL;
4886 switch(vid.renderpath)
4888 case RENDERPATH_D3D9:
4891 r_hlsl_permutation_t *p;
4892 r_hlsl_permutation = NULL;
4893 // cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4894 // cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4895 // cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4896 // cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4897 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
4898 for (i = 0;i < limit;i++)
4900 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
4902 if (p->vertexshader)
4903 IDirect3DVertexShader9_Release(p->vertexshader);
4905 IDirect3DPixelShader9_Release(p->pixelshader);
4906 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
4909 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4913 case RENDERPATH_D3D10:
4914 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4916 case RENDERPATH_D3D11:
4917 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4919 case RENDERPATH_GL20:
4921 r_glsl_permutation_t *p;
4922 r_glsl_permutation = NULL;
4923 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4924 for (i = 0;i < limit;i++)
4926 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4928 GL_Backend_FreeProgram(p->program);
4929 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4932 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4935 case RENDERPATH_CGGL:
4938 r_cg_permutation_t *p;
4939 r_cg_permutation = NULL;
4940 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4941 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4942 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4943 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4944 limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4945 for (i = 0;i < limit;i++)
4947 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4950 cgDestroyProgram(p->vprogram);
4952 cgDestroyProgram(p->fprogram);
4953 Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4956 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4960 case RENDERPATH_GL13:
4961 case RENDERPATH_GL11:
4966 void R_GLSL_DumpShader_f(void)
4971 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4974 FS_Print(file, "/* The engine may define the following macros:\n");
4975 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4976 for (i = 0;i < SHADERMODE_COUNT;i++)
4977 FS_Print(file, glslshadermodeinfo[i].pretext);
4978 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4979 FS_Print(file, shaderpermutationinfo[i].pretext);
4980 FS_Print(file, "*/\n");
4981 FS_Print(file, builtinshaderstring);
4983 Con_Printf("glsl/default.glsl written\n");
4986 Con_Printf("failed to write to glsl/default.glsl\n");
4989 file = FS_OpenRealFile("cg/default.cg", "w", false);
4992 FS_Print(file, "/* The engine may define the following macros:\n");
4993 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4994 for (i = 0;i < SHADERMODE_COUNT;i++)
4995 FS_Print(file, cgshadermodeinfo[i].pretext);
4996 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4997 FS_Print(file, shaderpermutationinfo[i].pretext);
4998 FS_Print(file, "*/\n");
4999 FS_Print(file, builtincgshaderstring);
5001 Con_Printf("cg/default.cg written\n");
5004 Con_Printf("failed to write to cg/default.cg\n");
5008 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
5011 FS_Print(file, "/* The engine may define the following macros:\n");
5012 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5013 for (i = 0;i < SHADERMODE_COUNT;i++)
5014 FS_Print(file, hlslshadermodeinfo[i].pretext);
5015 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5016 FS_Print(file, shaderpermutationinfo[i].pretext);
5017 FS_Print(file, "*/\n");
5018 FS_Print(file, builtincgshaderstring);
5020 Con_Printf("hlsl/default.hlsl written\n");
5023 Con_Printf("failed to write to hlsl/default.hlsl\n");
5027 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
5030 texturemode = GL_MODULATE;
5031 switch (vid.renderpath)
5033 case RENDERPATH_D3D9:
5035 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5036 R_Mesh_TexBind(GL20TU_FIRST , first );
5037 R_Mesh_TexBind(GL20TU_SECOND, second);
5040 case RENDERPATH_D3D10:
5041 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5043 case RENDERPATH_D3D11:
5044 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5046 case RENDERPATH_GL20:
5047 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5048 R_Mesh_TexBind(GL20TU_FIRST , first );
5049 R_Mesh_TexBind(GL20TU_SECOND, second);
5051 case RENDERPATH_CGGL:
5054 R_SetupShader_SetPermutationCG(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5055 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
5056 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
5059 case RENDERPATH_GL13:
5060 R_Mesh_TexBind(0, first );
5061 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
5062 R_Mesh_TexBind(1, second);
5064 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
5066 case RENDERPATH_GL11:
5067 R_Mesh_TexBind(0, first );
5072 void R_SetupShader_DepthOrShadow(void)
5074 switch (vid.renderpath)
5076 case RENDERPATH_D3D9:
5078 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5081 case RENDERPATH_D3D10:
5082 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5084 case RENDERPATH_D3D11:
5085 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5087 case RENDERPATH_GL20:
5088 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5090 case RENDERPATH_CGGL:
5092 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5095 case RENDERPATH_GL13:
5096 R_Mesh_TexBind(0, 0);
5097 R_Mesh_TexBind(1, 0);
5099 case RENDERPATH_GL11:
5100 R_Mesh_TexBind(0, 0);
5105 void R_SetupShader_ShowDepth(void)
5107 switch (vid.renderpath)
5109 case RENDERPATH_D3D9:
5111 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5114 case RENDERPATH_D3D10:
5115 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5117 case RENDERPATH_D3D11:
5118 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5120 case RENDERPATH_GL20:
5121 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5123 case RENDERPATH_CGGL:
5125 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5128 case RENDERPATH_GL13:
5130 case RENDERPATH_GL11:
5135 extern qboolean r_shadow_usingdeferredprepass;
5136 extern cvar_t r_shadow_deferred_8bitrange;
5137 extern rtexture_t *r_shadow_attenuationgradienttexture;
5138 extern rtexture_t *r_shadow_attenuation2dtexture;
5139 extern rtexture_t *r_shadow_attenuation3dtexture;
5140 extern qboolean r_shadow_usingshadowmap2d;
5141 extern qboolean r_shadow_usingshadowmaportho;
5142 extern float r_shadow_shadowmap_texturescale[2];
5143 extern float r_shadow_shadowmap_parameters[4];
5144 extern qboolean r_shadow_shadowmapvsdct;
5145 extern qboolean r_shadow_shadowmapsampler;
5146 extern int r_shadow_shadowmappcf;
5147 extern rtexture_t *r_shadow_shadowmap2dtexture;
5148 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5149 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5150 extern matrix4x4_t r_shadow_shadowmapmatrix;
5151 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5152 extern int r_shadow_prepass_width;
5153 extern int r_shadow_prepass_height;
5154 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5155 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5156 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
5157 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5158 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5159 extern cvar_t gl_mesh_separatearrays;
5160 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5162 // a blendfunc allows colormod if:
5163 // a) it can never keep the destination pixel invariant, or
5164 // b) it can keep the destination pixel invariant, and still can do so if colormodded
5165 // this is to prevent unintended side effects from colormod
5168 // IF there is a (s, sa) for which for all (d, da),
5169 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5170 // THEN, for this (s, sa) and all (colormod, d, da):
5171 // s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5172 // OBVIOUSLY, this means that
5173 // s*colormod * src(s*colormod, d, sa, da) = 0
5174 // dst(s*colormod, d, sa, da) = 1
5176 // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5178 // main condition to leave dst color invariant:
5179 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5181 // s * 0 + d * dst(s, d, sa, da) == d
5182 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5183 // => colormod is a problem for GL_SRC_COLOR only
5185 // s + d * dst(s, d, sa, da) == d
5187 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5188 // => colormod is never problematic for these
5189 // src == GL_SRC_COLOR:
5190 // s*s + d * dst(s, d, sa, da) == d
5192 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5193 // => colormod is never problematic for these
5194 // src == GL_ONE_MINUS_SRC_COLOR:
5195 // s*(1-s) + d * dst(s, d, sa, da) == d
5196 // => s == 0 or s == 1
5197 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5198 // => colormod is a problem for GL_SRC_COLOR only
5199 // src == GL_DST_COLOR
5200 // s*d + d * dst(s, d, sa, da) == d
5202 // => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5203 // => colormod is always a problem
5206 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5207 // => colormod is never problematic for these
5208 // => BUT, we do not know s! We must assume it is problematic
5209 // then... except in GL_ONE case, where we know all invariant
5211 // src == GL_ONE_MINUS_DST_COLOR
5212 // s*(1-d) + d * dst(s, d, sa, da) == d
5213 // => s == 0 (1-d is impossible to handle for our desired result)
5214 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5215 // => colormod is never problematic for these
5216 // src == GL_SRC_ALPHA
5217 // s*sa + d * dst(s, d, sa, da) == d
5218 // => s == 0, or sa == 0
5219 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5220 // => colormod breaks in the case GL_SRC_COLOR only
5221 // src == GL_ONE_MINUS_SRC_ALPHA
5222 // s*(1-sa) + d * dst(s, d, sa, da) == d
5223 // => s == 0, or sa == 1
5224 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5225 // => colormod breaks in the case GL_SRC_COLOR only
5226 // src == GL_DST_ALPHA
5227 // s*da + d * dst(s, d, sa, da) == d
5229 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5230 // => colormod is never problematic for these
5235 case GL_ONE_MINUS_SRC_COLOR:
5237 case GL_ONE_MINUS_SRC_ALPHA:
5238 if(dst == GL_SRC_COLOR)
5243 case GL_ONE_MINUS_DST_COLOR:
5245 case GL_ONE_MINUS_DST_ALPHA:
5255 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane)
5257 // select a permutation of the lighting shader appropriate to this
5258 // combination of texture, entity, light source, and fogging, only use the
5259 // minimum features necessary to avoid wasting rendering time in the
5260 // fragment shader on features that are not being used
5261 unsigned int permutation = 0;
5262 unsigned int mode = 0;
5263 qboolean allow_colormod;
5264 static float dummy_colormod[3] = {1, 1, 1};
5265 float *colormod = rsurface.colormod;
5267 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5268 if (rsurfacepass == RSURFPASS_BACKGROUND)
5270 // distorted background
5271 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5273 mode = SHADERMODE_WATER;
5274 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
5275 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
5276 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5277 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5279 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5281 mode = SHADERMODE_REFRACTION;
5282 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5283 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5287 mode = SHADERMODE_GENERIC;
5288 permutation |= SHADERPERMUTATION_DIFFUSE;
5289 GL_BlendFunc(GL_ONE, GL_ZERO);
5290 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5292 GL_AlphaTest(false);
5294 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5296 if (r_glsl_offsetmapping.integer)
5298 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5299 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5300 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5301 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5302 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5304 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5305 if (r_glsl_offsetmapping_reliefmapping.integer)
5306 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5309 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5310 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5311 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5312 permutation |= SHADERPERMUTATION_ALPHAKILL;
5313 // normalmap (deferred prepass), may use alpha test on diffuse
5314 mode = SHADERMODE_DEFERREDGEOMETRY;
5315 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5316 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5317 GL_AlphaTest(false);
5318 GL_BlendFunc(GL_ONE, GL_ZERO);
5319 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5321 else if (rsurfacepass == RSURFPASS_RTLIGHT)
5323 if (r_glsl_offsetmapping.integer)
5325 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5326 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5327 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5328 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5329 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5331 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5332 if (r_glsl_offsetmapping_reliefmapping.integer)
5333 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5336 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5337 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5339 mode = SHADERMODE_LIGHTSOURCE;
5340 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5341 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5342 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5343 permutation |= SHADERPERMUTATION_CUBEFILTER;
5344 if (diffusescale > 0)
5345 permutation |= SHADERPERMUTATION_DIFFUSE;
5346 if (specularscale > 0)
5348 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5349 if (r_shadow_glossexact.integer)
5350 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5352 if (r_refdef.fogenabled)
5353 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5354 if (rsurface.texture->colormapping)
5355 permutation |= SHADERPERMUTATION_COLORMAPPING;
5356 if (r_shadow_usingshadowmap2d)
5358 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5359 if(r_shadow_shadowmapvsdct)
5360 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5362 if (r_shadow_shadowmapsampler)
5363 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5364 if (r_shadow_shadowmappcf > 1)
5365 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5366 else if (r_shadow_shadowmappcf)
5367 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5369 if (rsurface.texture->reflectmasktexture)
5370 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5371 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5372 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5373 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5375 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5377 if (r_glsl_offsetmapping.integer)
5379 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5380 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5381 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5382 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5383 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5385 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5386 if (r_glsl_offsetmapping_reliefmapping.integer)
5387 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5390 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5391 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5392 // unshaded geometry (fullbright or ambient model lighting)
5393 mode = SHADERMODE_FLATCOLOR;
5394 ambientscale = diffusescale = specularscale = 0;
5395 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5396 permutation |= SHADERPERMUTATION_GLOW;
5397 if (r_refdef.fogenabled)
5398 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5399 if (rsurface.texture->colormapping)
5400 permutation |= SHADERPERMUTATION_COLORMAPPING;
5401 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5403 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5404 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5406 if (r_shadow_shadowmapsampler)
5407 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5408 if (r_shadow_shadowmappcf > 1)
5409 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5410 else if (r_shadow_shadowmappcf)
5411 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5413 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5414 permutation |= SHADERPERMUTATION_REFLECTION;
5415 if (rsurface.texture->reflectmasktexture)
5416 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5417 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5418 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5419 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5421 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5423 if (r_glsl_offsetmapping.integer)
5425 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5426 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5427 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5428 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5429 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5431 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5432 if (r_glsl_offsetmapping_reliefmapping.integer)
5433 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5436 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5437 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5438 // directional model lighting
5439 mode = SHADERMODE_LIGHTDIRECTION;
5440 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5441 permutation |= SHADERPERMUTATION_GLOW;
5442 permutation |= SHADERPERMUTATION_DIFFUSE;
5443 if (specularscale > 0)
5445 permutation |= SHADERPERMUTATION_SPECULAR;
5446 if (r_shadow_glossexact.integer)
5447 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5449 if (r_refdef.fogenabled)
5450 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5451 if (rsurface.texture->colormapping)
5452 permutation |= SHADERPERMUTATION_COLORMAPPING;
5453 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5455 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5456 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5458 if (r_shadow_shadowmapsampler)
5459 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5460 if (r_shadow_shadowmappcf > 1)
5461 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5462 else if (r_shadow_shadowmappcf)
5463 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5465 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5466 permutation |= SHADERPERMUTATION_REFLECTION;
5467 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5468 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5469 if (rsurface.texture->reflectmasktexture)
5470 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5471 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5472 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5473 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5475 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5477 if (r_glsl_offsetmapping.integer)
5479 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5480 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5481 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5482 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5483 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5485 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5486 if (r_glsl_offsetmapping_reliefmapping.integer)
5487 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5490 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5491 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5492 // ambient model lighting
5493 mode = SHADERMODE_LIGHTDIRECTION;
5494 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5495 permutation |= SHADERPERMUTATION_GLOW;
5496 if (r_refdef.fogenabled)
5497 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5498 if (rsurface.texture->colormapping)
5499 permutation |= SHADERPERMUTATION_COLORMAPPING;
5500 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5502 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5503 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5505 if (r_shadow_shadowmapsampler)
5506 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5507 if (r_shadow_shadowmappcf > 1)
5508 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5509 else if (r_shadow_shadowmappcf)
5510 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5512 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5513 permutation |= SHADERPERMUTATION_REFLECTION;
5514 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5515 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5516 if (rsurface.texture->reflectmasktexture)
5517 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5518 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5519 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5520 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5524 if (r_glsl_offsetmapping.integer)
5526 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5527 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5528 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5529 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5530 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5532 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5533 if (r_glsl_offsetmapping_reliefmapping.integer)
5534 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5537 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5538 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5540 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5541 permutation |= SHADERPERMUTATION_GLOW;
5542 if (r_refdef.fogenabled)
5543 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5544 if (rsurface.texture->colormapping)
5545 permutation |= SHADERPERMUTATION_COLORMAPPING;
5546 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5548 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5549 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5551 if (r_shadow_shadowmapsampler)
5552 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5553 if (r_shadow_shadowmappcf > 1)
5554 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5555 else if (r_shadow_shadowmappcf)
5556 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5558 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5559 permutation |= SHADERPERMUTATION_REFLECTION;
5560 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5561 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5562 if (rsurface.texture->reflectmasktexture)
5563 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5564 if (FAKELIGHT_ENABLED)
5566 // fake lightmapping (q1bsp, q3bsp, fullbright map)
5567 mode = SHADERMODE_FAKELIGHT;
5568 permutation |= SHADERPERMUTATION_DIFFUSE;
5569 if (specularscale > 0)
5571 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5572 if (r_shadow_glossexact.integer)
5573 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5576 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5578 // deluxemapping (light direction texture)
5579 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5580 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5582 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5583 permutation |= SHADERPERMUTATION_DIFFUSE;
5584 if (specularscale > 0)
5586 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5587 if (r_shadow_glossexact.integer)
5588 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5591 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5593 // fake deluxemapping (uniform light direction in tangentspace)
5594 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5595 permutation |= SHADERPERMUTATION_DIFFUSE;
5596 if (specularscale > 0)
5598 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5599 if (r_shadow_glossexact.integer)
5600 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5603 else if (rsurface.uselightmaptexture)
5605 // ordinary lightmapping (q1bsp, q3bsp)
5606 mode = SHADERMODE_LIGHTMAP;
5610 // ordinary vertex coloring (q3bsp)
5611 mode = SHADERMODE_VERTEXCOLOR;
5613 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5614 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5615 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5618 colormod = dummy_colormod;
5619 switch(vid.renderpath)
5621 case RENDERPATH_D3D9:
5623 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
5624 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5625 R_SetupShader_SetPermutationHLSL(mode, permutation);
5626 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5627 if (mode == SHADERMODE_LIGHTSOURCE)
5629 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5630 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5634 if (mode == SHADERMODE_LIGHTDIRECTION)
5636 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5639 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5640 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5641 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5642 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5643 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5645 if (mode == SHADERMODE_LIGHTSOURCE)
5647 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5648 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5649 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5650 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5651 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5653 // additive passes are only darkened by fog, not tinted
5654 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5655 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5659 if (mode == SHADERMODE_FLATCOLOR)
5661 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5663 else if (mode == SHADERMODE_LIGHTDIRECTION)
5665 hlslPSSetParameter3f(D3DPSREGISTER_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]);
5666 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5667 hlslPSSetParameter3f(D3DPSREGISTER_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);
5668 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
5669 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5670 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5671 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5675 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5676 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5677 hlslPSSetParameter3f(D3DPSREGISTER_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);
5678 hlslPSSetParameter3f(D3DPSREGISTER_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);
5679 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5681 // additive passes are only darkened by fog, not tinted
5682 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5683 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5685 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5686 hlslPSSetParameter4f(D3DPSREGISTER_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);
5687 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5688 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5689 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5690 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5691 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5692 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5693 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5694 if (mode == SHADERMODE_WATER)
5695 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5697 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5698 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5699 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5700 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
5701 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5702 if (rsurface.texture->pantstexture)
5703 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5705 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5706 if (rsurface.texture->shirttexture)
5707 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5709 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5710 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5711 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5712 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5713 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5714 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5715 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5716 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5718 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5719 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5720 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5721 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5722 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5723 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5724 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5725 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5726 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5727 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5728 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5729 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5730 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5731 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5732 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5733 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5734 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5735 if (rsurfacepass == RSURFPASS_BACKGROUND)
5737 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5738 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5739 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5743 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5745 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5746 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5747 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5748 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5749 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5751 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5752 if (rsurface.rtlight)
5754 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5755 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5760 case RENDERPATH_D3D10:
5761 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5763 case RENDERPATH_D3D11:
5764 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5766 case RENDERPATH_GL20:
5767 if (gl_mesh_separatearrays.integer)
5769 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
5770 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5771 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5772 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5773 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5774 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5775 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5776 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5780 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
5781 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5783 R_SetupShader_SetPermutationGLSL(mode, permutation);
5784 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5785 if (mode == SHADERMODE_LIGHTSOURCE)
5787 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5788 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5789 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5790 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5791 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5792 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);
5794 // additive passes are only darkened by fog, not tinted
5795 if (r_glsl_permutation->loc_FogColor >= 0)
5796 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5797 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5801 if (mode == SHADERMODE_FLATCOLOR)
5803 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5805 else if (mode == SHADERMODE_LIGHTDIRECTION)
5807 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]);
5808 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]);
5809 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);
5810 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);
5811 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);
5812 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]);
5813 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]);
5817 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]);
5818 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]);
5819 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);
5820 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);
5821 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);
5823 // additive passes are only darkened by fog, not tinted
5824 if (r_glsl_permutation->loc_FogColor >= 0)
5826 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5827 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5829 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5831 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);
5832 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]);
5833 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]);
5834 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]);
5835 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]);
5836 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5837 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5838 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5839 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]);
5841 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5842 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5843 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5844 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]);
5845 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]);
5847 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5848 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));
5849 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5850 if (r_glsl_permutation->loc_Color_Pants >= 0)
5852 if (rsurface.texture->pantstexture)
5853 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5855 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5857 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5859 if (rsurface.texture->shirttexture)
5860 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5862 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5864 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]);
5865 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5866 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5867 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5868 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5869 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]);
5870 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5872 // if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_texture_white );
5873 // if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_texture_white );
5874 // if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS , r_texture_gammaramps );
5875 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5876 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5877 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5878 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5879 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5880 if (r_glsl_permutation->loc_Texture_SecondaryColor >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5881 if (r_glsl_permutation->loc_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5882 if (r_glsl_permutation->loc_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5883 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5884 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5885 if (r_glsl_permutation->loc_Texture_ReflectMask >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5886 if (r_glsl_permutation->loc_Texture_ReflectCube >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5887 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5888 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5889 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5890 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5891 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5892 if (rsurfacepass == RSURFPASS_BACKGROUND)
5894 if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5895 else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5896 if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5900 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5902 // if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5903 // if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5904 if (r_glsl_permutation->loc_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5905 if (r_glsl_permutation->loc_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5906 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5908 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture );
5909 if (rsurface.rtlight)
5911 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5912 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5917 case RENDERPATH_CGGL:
5919 if (gl_mesh_separatearrays.integer)
5921 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
5922 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5923 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5924 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5925 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5926 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5927 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5928 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5932 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
5933 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5935 R_SetupShader_SetPermutationCG(mode, permutation);
5936 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
5937 if (mode == SHADERMODE_LIGHTSOURCE)
5939 if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
5940 if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5944 if (mode == SHADERMODE_LIGHTDIRECTION)
5946 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
5949 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
5950 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
5951 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
5952 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5953 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
5956 if (mode == SHADERMODE_LIGHTSOURCE)
5958 if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5959 if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
5960 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
5961 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
5962 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
5964 // additive passes are only darkened by fog, not tinted
5965 if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
5966 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5970 if (mode == SHADERMODE_FLATCOLOR)
5972 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
5974 else if (mode == SHADERMODE_LIGHTDIRECTION)
5976 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
5977 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
5978 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
5979 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
5980 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
5981 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
5982 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
5986 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
5987 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
5988 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
5989 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
5990 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
5992 // additive passes are only darkened by fog, not tinted
5993 if (r_cg_permutation->fp_FogColor)
5995 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5996 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
5998 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6001 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
6002 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
6003 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
6004 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
6005 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
6006 if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
6007 if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
6008 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
6009 if (r_cg_permutation->fp_NormalmapScrollBlend) cgGLSetParameter2f(r_cg_permutation->fp_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
6011 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
6012 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
6013 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
6014 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
6015 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6016 if (r_cg_permutation->fp_Color_Pants)
6018 if (rsurface.texture->pantstexture)
6019 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6021 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
6024 if (r_cg_permutation->fp_Color_Shirt)
6026 if (rsurface.texture->shirttexture)
6027 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6029 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
6032 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
6033 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
6034 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
6035 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
6036 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
6037 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
6038 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6040 // if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_texture_white );CHECKCGERROR
6041 // if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_texture_white );CHECKCGERROR
6042 // if (r_cg_permutation->fp_Texture_GammaRamps ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps , r_texture_gammaramps );CHECKCGERROR
6043 if (r_cg_permutation->fp_Texture_Normal ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal , rsurface.texture->nmaptexture );CHECKCGERROR
6044 if (r_cg_permutation->fp_Texture_Color ) CG_BindTexture(r_cg_permutation->fp_Texture_Color , rsurface.texture->basetexture );CHECKCGERROR
6045 if (r_cg_permutation->fp_Texture_Gloss ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss , rsurface.texture->glosstexture );CHECKCGERROR
6046 if (r_cg_permutation->fp_Texture_Glow ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow , rsurface.texture->glowtexture );CHECKCGERROR
6047 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture );CHECKCGERROR
6048 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );CHECKCGERROR
6049 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );CHECKCGERROR
6050 if (r_cg_permutation->fp_Texture_SecondaryGlow ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );CHECKCGERROR
6051 if (r_cg_permutation->fp_Texture_Pants ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants , rsurface.texture->pantstexture );CHECKCGERROR
6052 if (r_cg_permutation->fp_Texture_Shirt ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt , rsurface.texture->shirttexture );CHECKCGERROR
6053 if (r_cg_permutation->fp_Texture_ReflectMask ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask , rsurface.texture->reflectmasktexture );CHECKCGERROR
6054 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
6055 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture );CHECKCGERROR
6056 if (r_cg_permutation->fp_Texture_FogMask ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask , r_texture_fogattenuation );CHECKCGERROR
6057 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
6058 if (r_cg_permutation->fp_Texture_Deluxemap ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
6059 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
6060 if (rsurfacepass == RSURFPASS_BACKGROUND)
6062 if (r_cg_permutation->fp_Texture_Refraction ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);CHECKCGERROR
6063 else if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);CHECKCGERROR
6064 if (r_cg_permutation->fp_Texture_Reflection ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);CHECKCGERROR
6068 if (r_cg_permutation->fp_Texture_Reflection ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);CHECKCGERROR
6070 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
6071 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
6072 if (r_cg_permutation->fp_Texture_ScreenDiffuse ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );CHECKCGERROR
6073 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );CHECKCGERROR
6074 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6076 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
6077 if (rsurface.rtlight)
6079 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
6080 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
6087 case RENDERPATH_GL13:
6088 case RENDERPATH_GL11:
6093 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6095 // select a permutation of the lighting shader appropriate to this
6096 // combination of texture, entity, light source, and fogging, only use the
6097 // minimum features necessary to avoid wasting rendering time in the
6098 // fragment shader on features that are not being used
6099 unsigned int permutation = 0;
6100 unsigned int mode = 0;
6101 const float *lightcolorbase = rtlight->currentcolor;
6102 float ambientscale = rtlight->ambientscale;
6103 float diffusescale = rtlight->diffusescale;
6104 float specularscale = rtlight->specularscale;
6105 // this is the location of the light in view space
6106 vec3_t viewlightorigin;
6107 // this transforms from view space (camera) to light space (cubemap)
6108 matrix4x4_t viewtolight;
6109 matrix4x4_t lighttoview;
6110 float viewtolight16f[16];
6111 float range = 1.0f / r_shadow_deferred_8bitrange.value;
6113 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6114 if (rtlight->currentcubemap != r_texture_whitecube)
6115 permutation |= SHADERPERMUTATION_CUBEFILTER;
6116 if (diffusescale > 0)
6117 permutation |= SHADERPERMUTATION_DIFFUSE;
6118 if (specularscale > 0)
6120 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6121 if (r_shadow_glossexact.integer)
6122 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
6124 if (r_shadow_usingshadowmap2d)
6126 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6127 if (r_shadow_shadowmapvsdct)
6128 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6130 if (r_shadow_shadowmapsampler)
6131 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6132 if (r_shadow_shadowmappcf > 1)
6133 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6134 else if (r_shadow_shadowmappcf)
6135 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6137 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6138 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6139 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6140 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6141 switch(vid.renderpath)
6143 case RENDERPATH_D3D9:
6145 R_SetupShader_SetPermutationHLSL(mode, permutation);
6146 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6147 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6148 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
6149 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
6150 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6151 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6152 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6153 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
6154 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6155 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6157 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
6158 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
6159 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
6160 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
6161 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
6162 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
6165 case RENDERPATH_D3D10:
6166 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6168 case RENDERPATH_D3D11:
6169 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6171 case RENDERPATH_GL20:
6172 R_SetupShader_SetPermutationGLSL(mode, permutation);
6173 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6174 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
6175 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);
6176 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);
6177 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);
6178 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]);
6179 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]);
6180 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB( r_glsl_permutation->loc_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
6181 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]);
6182 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6184 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
6185 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
6186 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
6187 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
6188 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
6189 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
6191 case RENDERPATH_CGGL:
6193 R_SetupShader_SetPermutationCG(mode, permutation);
6194 if (r_cg_permutation->fp_LightPosition ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6195 if (r_cg_permutation->fp_ViewToLight ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6196 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
6197 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
6198 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
6199 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
6200 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
6201 if (r_cg_permutation->fp_SpecularPower ) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
6202 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
6203 if (r_cg_permutation->fp_PixelToScreenTexCoord ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6205 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
6206 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
6207 if (r_cg_permutation->fp_Texture_ScreenNormalMap ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
6208 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
6209 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
6210 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
6213 case RENDERPATH_GL13:
6214 case RENDERPATH_GL11:
6219 #define SKINFRAME_HASH 1024
6223 int loadsequence; // incremented each level change
6224 memexpandablearray_t array;
6225 skinframe_t *hash[SKINFRAME_HASH];
6228 r_skinframe_t r_skinframe;
6230 void R_SkinFrame_PrepareForPurge(void)
6232 r_skinframe.loadsequence++;
6233 // wrap it without hitting zero
6234 if (r_skinframe.loadsequence >= 200)
6235 r_skinframe.loadsequence = 1;
6238 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6242 // mark the skinframe as used for the purging code
6243 skinframe->loadsequence = r_skinframe.loadsequence;
6246 void R_SkinFrame_Purge(void)
6250 for (i = 0;i < SKINFRAME_HASH;i++)
6252 for (s = r_skinframe.hash[i];s;s = s->next)
6254 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6256 if (s->merged == s->base)
6258 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6259 R_PurgeTexture(s->stain );s->stain = NULL;
6260 R_PurgeTexture(s->merged);s->merged = NULL;
6261 R_PurgeTexture(s->base );s->base = NULL;
6262 R_PurgeTexture(s->pants );s->pants = NULL;
6263 R_PurgeTexture(s->shirt );s->shirt = NULL;
6264 R_PurgeTexture(s->nmap );s->nmap = NULL;
6265 R_PurgeTexture(s->gloss );s->gloss = NULL;
6266 R_PurgeTexture(s->glow );s->glow = NULL;
6267 R_PurgeTexture(s->fog );s->fog = NULL;
6268 R_PurgeTexture(s->reflect);s->reflect = NULL;
6269 s->loadsequence = 0;
6275 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6277 char basename[MAX_QPATH];
6279 Image_StripImageExtension(name, basename, sizeof(basename));
6281 if( last == NULL ) {
6283 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6284 item = r_skinframe.hash[hashindex];
6289 // linearly search through the hash bucket
6290 for( ; item ; item = item->next ) {
6291 if( !strcmp( item->basename, basename ) ) {
6298 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6302 char basename[MAX_QPATH];
6304 Image_StripImageExtension(name, basename, sizeof(basename));
6306 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6307 for (item = r_skinframe.hash[hashindex];item;item = item->next)
6308 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6312 rtexture_t *dyntexture;
6313 // check whether its a dynamic texture
6314 dyntexture = CL_GetDynTexture( basename );
6315 if (!add && !dyntexture)
6317 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6318 memset(item, 0, sizeof(*item));
6319 strlcpy(item->basename, basename, sizeof(item->basename));
6320 item->base = dyntexture; // either NULL or dyntexture handle
6321 item->textureflags = textureflags;
6322 item->comparewidth = comparewidth;
6323 item->compareheight = compareheight;
6324 item->comparecrc = comparecrc;
6325 item->next = r_skinframe.hash[hashindex];
6326 r_skinframe.hash[hashindex] = item;
6328 else if( item->base == NULL )
6330 rtexture_t *dyntexture;
6331 // check whether its a dynamic texture
6332 // 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]
6333 dyntexture = CL_GetDynTexture( basename );
6334 item->base = dyntexture; // either NULL or dyntexture handle
6337 R_SkinFrame_MarkUsed(item);
6341 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6343 unsigned long long avgcolor[5], wsum; \
6351 for(pix = 0; pix < cnt; ++pix) \
6354 for(comp = 0; comp < 3; ++comp) \
6356 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6359 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6361 for(comp = 0; comp < 3; ++comp) \
6362 avgcolor[comp] += getpixel * w; \
6365 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6366 avgcolor[4] += getpixel; \
6368 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6370 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6371 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6372 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6373 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6376 extern cvar_t gl_picmip;
6377 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6380 unsigned char *pixels;
6381 unsigned char *bumppixels;
6382 unsigned char *basepixels = NULL;
6383 int basepixels_width = 0;
6384 int basepixels_height = 0;
6385 skinframe_t *skinframe;
6386 rtexture_t *ddsbase = NULL;
6387 qboolean ddshasalpha = false;
6388 float ddsavgcolor[4];
6389 char basename[MAX_QPATH];
6390 int miplevel = R_PicmipForFlags(textureflags);
6391 int savemiplevel = miplevel;
6394 if (cls.state == ca_dedicated)
6397 // return an existing skinframe if already loaded
6398 // if loading of the first image fails, don't make a new skinframe as it
6399 // would cause all future lookups of this to be missing
6400 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6401 if (skinframe && skinframe->base)
6404 Image_StripImageExtension(name, basename, sizeof(basename));
6406 // check for DDS texture file first
6407 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6409 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6410 if (basepixels == NULL)
6414 // FIXME handle miplevel
6416 if (developer_loading.integer)
6417 Con_Printf("loading skin \"%s\"\n", name);
6419 // we've got some pixels to store, so really allocate this new texture now
6421 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6422 skinframe->stain = NULL;
6423 skinframe->merged = NULL;
6424 skinframe->base = NULL;
6425 skinframe->pants = NULL;
6426 skinframe->shirt = NULL;
6427 skinframe->nmap = NULL;
6428 skinframe->gloss = NULL;
6429 skinframe->glow = NULL;
6430 skinframe->fog = NULL;
6431 skinframe->reflect = NULL;
6432 skinframe->hasalpha = false;
6436 skinframe->base = ddsbase;
6437 skinframe->hasalpha = ddshasalpha;
6438 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6439 if (r_loadfog && skinframe->hasalpha)
6440 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6441 //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]);
6445 basepixels_width = image_width;
6446 basepixels_height = image_height;
6447 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);
6448 if (textureflags & TEXF_ALPHA)
6450 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6452 if (basepixels[j] < 255)
6454 skinframe->hasalpha = true;
6458 if (r_loadfog && skinframe->hasalpha)
6460 // has transparent pixels
6461 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6462 for (j = 0;j < image_width * image_height * 4;j += 4)
6467 pixels[j+3] = basepixels[j+3];
6469 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);
6473 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6474 //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]);
6475 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6476 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6477 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6478 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6483 mymiplevel = savemiplevel;
6484 if (r_loadnormalmap)
6485 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);
6486 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6488 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6489 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6490 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6491 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6494 // _norm is the name used by tenebrae and has been adopted as standard
6495 if (r_loadnormalmap && skinframe->nmap == NULL)
6497 mymiplevel = savemiplevel;
6498 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6500 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);
6504 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6506 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6507 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6508 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);
6510 Mem_Free(bumppixels);
6512 else if (r_shadow_bumpscale_basetexture.value > 0)
6514 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6515 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6516 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);
6519 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6520 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6523 // _luma is supported only for tenebrae compatibility
6524 // _glow is the preferred name
6525 mymiplevel = savemiplevel;
6526 if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel))))
6528 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);
6529 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6530 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6531 Mem_Free(pixels);pixels = NULL;
6534 mymiplevel = savemiplevel;
6535 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6537 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);
6538 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6539 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6544 mymiplevel = savemiplevel;
6545 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6547 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);
6548 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6549 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6554 mymiplevel = savemiplevel;
6555 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6557 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);
6558 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6559 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6564 mymiplevel = savemiplevel;
6565 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6567 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);
6568 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6569 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6575 Mem_Free(basepixels);
6580 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6581 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6584 unsigned char *temp1, *temp2;
6585 skinframe_t *skinframe;
6587 if (cls.state == ca_dedicated)
6590 // if already loaded just return it, otherwise make a new skinframe
6591 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6592 if (skinframe && skinframe->base)
6595 skinframe->stain = NULL;
6596 skinframe->merged = NULL;
6597 skinframe->base = NULL;
6598 skinframe->pants = NULL;
6599 skinframe->shirt = NULL;
6600 skinframe->nmap = NULL;
6601 skinframe->gloss = NULL;
6602 skinframe->glow = NULL;
6603 skinframe->fog = NULL;
6604 skinframe->reflect = NULL;
6605 skinframe->hasalpha = false;
6607 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6611 if (developer_loading.integer)
6612 Con_Printf("loading 32bit skin \"%s\"\n", name);
6614 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6616 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6617 temp2 = temp1 + width * height * 4;
6618 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6619 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);
6622 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6623 if (textureflags & TEXF_ALPHA)
6625 for (i = 3;i < width * height * 4;i += 4)
6627 if (skindata[i] < 255)
6629 skinframe->hasalpha = true;
6633 if (r_loadfog && skinframe->hasalpha)
6635 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6636 memcpy(fogpixels, skindata, width * height * 4);
6637 for (i = 0;i < width * height * 4;i += 4)
6638 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6639 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6640 Mem_Free(fogpixels);
6644 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6645 //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]);
6650 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6654 skinframe_t *skinframe;
6656 if (cls.state == ca_dedicated)
6659 // if already loaded just return it, otherwise make a new skinframe
6660 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6661 if (skinframe && skinframe->base)
6664 skinframe->stain = NULL;
6665 skinframe->merged = NULL;
6666 skinframe->base = NULL;
6667 skinframe->pants = NULL;
6668 skinframe->shirt = NULL;
6669 skinframe->nmap = NULL;
6670 skinframe->gloss = NULL;
6671 skinframe->glow = NULL;
6672 skinframe->fog = NULL;
6673 skinframe->reflect = NULL;
6674 skinframe->hasalpha = false;
6676 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6680 if (developer_loading.integer)
6681 Con_Printf("loading quake skin \"%s\"\n", name);
6683 // 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)
6684 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height);
6685 memcpy(skinframe->qpixels, skindata, width*height);
6686 skinframe->qwidth = width;
6687 skinframe->qheight = height;
6690 for (i = 0;i < width * height;i++)
6691 featuresmask |= palette_featureflags[skindata[i]];
6693 skinframe->hasalpha = false;
6694 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6695 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6696 skinframe->qgeneratemerged = true;
6697 skinframe->qgeneratebase = skinframe->qhascolormapping;
6698 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6700 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6701 //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]);
6706 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6710 unsigned char *skindata;
6712 if (!skinframe->qpixels)
6715 if (!skinframe->qhascolormapping)
6716 colormapped = false;
6720 if (!skinframe->qgeneratebase)
6725 if (!skinframe->qgeneratemerged)
6729 width = skinframe->qwidth;
6730 height = skinframe->qheight;
6731 skindata = skinframe->qpixels;
6733 if (skinframe->qgeneratenmap)
6735 unsigned char *temp1, *temp2;
6736 skinframe->qgeneratenmap = false;
6737 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6738 temp2 = temp1 + width * height * 4;
6739 // use either a custom palette or the quake palette
6740 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6741 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6742 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);
6746 if (skinframe->qgenerateglow)
6748 skinframe->qgenerateglow = false;
6749 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6754 skinframe->qgeneratebase = false;
6755 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);
6756 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6757 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6761 skinframe->qgeneratemerged = false;
6762 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);
6765 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6767 Mem_Free(skinframe->qpixels);
6768 skinframe->qpixels = NULL;
6772 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)
6775 skinframe_t *skinframe;
6777 if (cls.state == ca_dedicated)
6780 // if already loaded just return it, otherwise make a new skinframe
6781 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6782 if (skinframe && skinframe->base)
6785 skinframe->stain = NULL;
6786 skinframe->merged = NULL;
6787 skinframe->base = NULL;
6788 skinframe->pants = NULL;
6789 skinframe->shirt = NULL;
6790 skinframe->nmap = NULL;
6791 skinframe->gloss = NULL;
6792 skinframe->glow = NULL;
6793 skinframe->fog = NULL;
6794 skinframe->reflect = NULL;
6795 skinframe->hasalpha = false;
6797 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6801 if (developer_loading.integer)
6802 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6804 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6805 if (textureflags & TEXF_ALPHA)
6807 for (i = 0;i < width * height;i++)
6809 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6811 skinframe->hasalpha = true;
6815 if (r_loadfog && skinframe->hasalpha)
6816 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6819 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6820 //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]);
6825 skinframe_t *R_SkinFrame_LoadMissing(void)
6827 skinframe_t *skinframe;
6829 if (cls.state == ca_dedicated)
6832 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6833 skinframe->stain = NULL;
6834 skinframe->merged = NULL;
6835 skinframe->base = NULL;
6836 skinframe->pants = NULL;
6837 skinframe->shirt = NULL;
6838 skinframe->nmap = NULL;
6839 skinframe->gloss = NULL;
6840 skinframe->glow = NULL;
6841 skinframe->fog = NULL;
6842 skinframe->reflect = NULL;
6843 skinframe->hasalpha = false;
6845 skinframe->avgcolor[0] = rand() / RAND_MAX;
6846 skinframe->avgcolor[1] = rand() / RAND_MAX;
6847 skinframe->avgcolor[2] = rand() / RAND_MAX;
6848 skinframe->avgcolor[3] = 1;
6853 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6854 typedef struct suffixinfo_s
6857 qboolean flipx, flipy, flipdiagonal;
6860 static suffixinfo_t suffix[3][6] =
6863 {"px", false, false, false},
6864 {"nx", false, false, false},
6865 {"py", false, false, false},
6866 {"ny", false, false, false},
6867 {"pz", false, false, false},
6868 {"nz", false, false, false}
6871 {"posx", false, false, false},
6872 {"negx", false, false, false},
6873 {"posy", false, false, false},
6874 {"negy", false, false, false},
6875 {"posz", false, false, false},
6876 {"negz", false, false, false}
6879 {"rt", true, false, true},
6880 {"lf", false, true, true},
6881 {"ft", true, true, false},
6882 {"bk", false, false, false},
6883 {"up", true, false, true},
6884 {"dn", true, false, true}
6888 static int componentorder[4] = {0, 1, 2, 3};
6890 rtexture_t *R_LoadCubemap(const char *basename)
6892 int i, j, cubemapsize;
6893 unsigned char *cubemappixels, *image_buffer;
6894 rtexture_t *cubemaptexture;
6896 // must start 0 so the first loadimagepixels has no requested width/height
6898 cubemappixels = NULL;
6899 cubemaptexture = NULL;
6900 // keep trying different suffix groups (posx, px, rt) until one loads
6901 for (j = 0;j < 3 && !cubemappixels;j++)
6903 // load the 6 images in the suffix group
6904 for (i = 0;i < 6;i++)
6906 // generate an image name based on the base and and suffix
6907 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6909 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
6911 // an image loaded, make sure width and height are equal
6912 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6914 // if this is the first image to load successfully, allocate the cubemap memory
6915 if (!cubemappixels && image_width >= 1)
6917 cubemapsize = image_width;
6918 // note this clears to black, so unavailable sides are black
6919 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6921 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6923 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);
6926 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6928 Mem_Free(image_buffer);
6932 // if a cubemap loaded, upload it
6935 if (developer_loading.integer)
6936 Con_Printf("loading cubemap \"%s\"\n", basename);
6938 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6939 Mem_Free(cubemappixels);
6943 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6944 if (developer_loading.integer)
6946 Con_Printf("(tried tried images ");
6947 for (j = 0;j < 3;j++)
6948 for (i = 0;i < 6;i++)
6949 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6950 Con_Print(" and was unable to find any of them).\n");
6953 return cubemaptexture;
6956 rtexture_t *R_GetCubemap(const char *basename)
6959 for (i = 0;i < r_texture_numcubemaps;i++)
6960 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6961 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6962 if (i >= MAX_CUBEMAPS)
6963 return r_texture_whitecube;
6964 r_texture_numcubemaps++;
6965 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6966 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6967 return r_texture_cubemaps[i].texture;
6970 void R_FreeCubemaps(void)
6973 for (i = 0;i < r_texture_numcubemaps;i++)
6975 if (developer_loading.integer)
6976 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6977 if (r_texture_cubemaps[i].texture)
6978 R_FreeTexture(r_texture_cubemaps[i].texture);
6980 r_texture_numcubemaps = 0;
6983 void R_Main_FreeViewCache(void)
6985 if (r_refdef.viewcache.entityvisible)
6986 Mem_Free(r_refdef.viewcache.entityvisible);
6987 if (r_refdef.viewcache.world_pvsbits)
6988 Mem_Free(r_refdef.viewcache.world_pvsbits);
6989 if (r_refdef.viewcache.world_leafvisible)
6990 Mem_Free(r_refdef.viewcache.world_leafvisible);
6991 if (r_refdef.viewcache.world_surfacevisible)
6992 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6993 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6996 void R_Main_ResizeViewCache(void)
6998 int numentities = r_refdef.scene.numentities;
6999 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
7000 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
7001 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
7002 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
7003 if (r_refdef.viewcache.maxentities < numentities)
7005 r_refdef.viewcache.maxentities = numentities;
7006 if (r_refdef.viewcache.entityvisible)
7007 Mem_Free(r_refdef.viewcache.entityvisible);
7008 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
7010 if (r_refdef.viewcache.world_numclusters != numclusters)
7012 r_refdef.viewcache.world_numclusters = numclusters;
7013 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
7014 if (r_refdef.viewcache.world_pvsbits)
7015 Mem_Free(r_refdef.viewcache.world_pvsbits);
7016 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
7018 if (r_refdef.viewcache.world_numleafs != numleafs)
7020 r_refdef.viewcache.world_numleafs = numleafs;
7021 if (r_refdef.viewcache.world_leafvisible)
7022 Mem_Free(r_refdef.viewcache.world_leafvisible);
7023 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
7025 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
7027 r_refdef.viewcache.world_numsurfaces = numsurfaces;
7028 if (r_refdef.viewcache.world_surfacevisible)
7029 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7030 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
7034 extern rtexture_t *loadingscreentexture;
7035 void gl_main_start(void)
7037 loadingscreentexture = NULL;
7038 r_texture_blanknormalmap = NULL;
7039 r_texture_white = NULL;
7040 r_texture_grey128 = NULL;
7041 r_texture_black = NULL;
7042 r_texture_whitecube = NULL;
7043 r_texture_normalizationcube = NULL;
7044 r_texture_fogattenuation = NULL;
7045 r_texture_fogheighttexture = NULL;
7046 r_texture_gammaramps = NULL;
7047 r_texture_numcubemaps = 0;
7049 r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
7050 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
7052 switch(vid.renderpath)
7054 case RENDERPATH_GL20:
7055 case RENDERPATH_CGGL:
7056 case RENDERPATH_D3D9:
7057 case RENDERPATH_D3D10:
7058 case RENDERPATH_D3D11:
7059 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7060 Cvar_SetValueQuick(&gl_combine, 1);
7061 Cvar_SetValueQuick(&r_glsl, 1);
7062 r_loadnormalmap = true;
7066 case RENDERPATH_GL13:
7067 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7068 Cvar_SetValueQuick(&gl_combine, 1);
7069 Cvar_SetValueQuick(&r_glsl, 0);
7070 r_loadnormalmap = false;
7071 r_loadgloss = false;
7074 case RENDERPATH_GL11:
7075 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7076 Cvar_SetValueQuick(&gl_combine, 0);
7077 Cvar_SetValueQuick(&r_glsl, 0);
7078 r_loadnormalmap = false;
7079 r_loadgloss = false;
7085 R_FrameData_Reset();
7089 memset(r_queries, 0, sizeof(r_queries));
7091 r_qwskincache = NULL;
7092 r_qwskincache_size = 0;
7094 // set up r_skinframe loading system for textures
7095 memset(&r_skinframe, 0, sizeof(r_skinframe));
7096 r_skinframe.loadsequence = 1;
7097 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7099 r_main_texturepool = R_AllocTexturePool();
7100 R_BuildBlankTextures();
7102 if (vid.support.arb_texture_cube_map)
7105 R_BuildNormalizationCube();
7107 r_texture_fogattenuation = NULL;
7108 r_texture_fogheighttexture = NULL;
7109 r_texture_gammaramps = NULL;
7110 //r_texture_fogintensity = NULL;
7111 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7112 memset(&r_waterstate, 0, sizeof(r_waterstate));
7113 r_glsl_permutation = NULL;
7114 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7115 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7116 glslshaderstring = NULL;
7118 r_cg_permutation = NULL;
7119 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7120 Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7121 cgshaderstring = NULL;
7124 r_hlsl_permutation = NULL;
7125 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7126 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7127 hlslshaderstring = NULL;
7129 memset(&r_svbsp, 0, sizeof (r_svbsp));
7131 r_refdef.fogmasktable_density = 0;
7134 void gl_main_shutdown(void)
7137 R_FrameData_Reset();
7139 R_Main_FreeViewCache();
7141 switch(vid.renderpath)
7143 case RENDERPATH_GL11:
7144 case RENDERPATH_GL13:
7145 case RENDERPATH_GL20:
7146 case RENDERPATH_CGGL:
7148 qglDeleteQueriesARB(r_maxqueries, r_queries);
7150 case RENDERPATH_D3D9:
7151 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7153 case RENDERPATH_D3D10:
7154 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7156 case RENDERPATH_D3D11:
7157 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7163 memset(r_queries, 0, sizeof(r_queries));
7165 r_qwskincache = NULL;
7166 r_qwskincache_size = 0;
7168 // clear out the r_skinframe state
7169 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7170 memset(&r_skinframe, 0, sizeof(r_skinframe));
7173 Mem_Free(r_svbsp.nodes);
7174 memset(&r_svbsp, 0, sizeof (r_svbsp));
7175 R_FreeTexturePool(&r_main_texturepool);
7176 loadingscreentexture = NULL;
7177 r_texture_blanknormalmap = NULL;
7178 r_texture_white = NULL;
7179 r_texture_grey128 = NULL;
7180 r_texture_black = NULL;
7181 r_texture_whitecube = NULL;
7182 r_texture_normalizationcube = NULL;
7183 r_texture_fogattenuation = NULL;
7184 r_texture_fogheighttexture = NULL;
7185 r_texture_gammaramps = NULL;
7186 r_texture_numcubemaps = 0;
7187 //r_texture_fogintensity = NULL;
7188 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7189 memset(&r_waterstate, 0, sizeof(r_waterstate));
7193 extern void CL_ParseEntityLump(char *entitystring);
7194 void gl_main_newmap(void)
7196 // FIXME: move this code to client
7197 char *entities, entname[MAX_QPATH];
7199 Mem_Free(r_qwskincache);
7200 r_qwskincache = NULL;
7201 r_qwskincache_size = 0;
7204 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7205 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7207 CL_ParseEntityLump(entities);
7211 if (cl.worldmodel->brush.entities)
7212 CL_ParseEntityLump(cl.worldmodel->brush.entities);
7214 R_Main_FreeViewCache();
7216 R_FrameData_Reset();
7219 void GL_Main_Init(void)
7221 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7223 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7224 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7225 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7226 if (gamemode == GAME_NEHAHRA)
7228 Cvar_RegisterVariable (&gl_fogenable);
7229 Cvar_RegisterVariable (&gl_fogdensity);
7230 Cvar_RegisterVariable (&gl_fogred);
7231 Cvar_RegisterVariable (&gl_foggreen);
7232 Cvar_RegisterVariable (&gl_fogblue);
7233 Cvar_RegisterVariable (&gl_fogstart);
7234 Cvar_RegisterVariable (&gl_fogend);
7235 Cvar_RegisterVariable (&gl_skyclip);
7237 Cvar_RegisterVariable(&r_motionblur);
7238 Cvar_RegisterVariable(&r_motionblur_maxblur);
7239 Cvar_RegisterVariable(&r_motionblur_bmin);
7240 Cvar_RegisterVariable(&r_motionblur_vmin);
7241 Cvar_RegisterVariable(&r_motionblur_vmax);
7242 Cvar_RegisterVariable(&r_motionblur_vcoeff);
7243 Cvar_RegisterVariable(&r_motionblur_randomize);
7244 Cvar_RegisterVariable(&r_damageblur);
7245 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7246 Cvar_RegisterVariable(&r_equalize_entities_minambient);
7247 Cvar_RegisterVariable(&r_equalize_entities_by);
7248 Cvar_RegisterVariable(&r_equalize_entities_to);
7249 Cvar_RegisterVariable(&r_depthfirst);
7250 Cvar_RegisterVariable(&r_useinfinitefarclip);
7251 Cvar_RegisterVariable(&r_farclip_base);
7252 Cvar_RegisterVariable(&r_farclip_world);
7253 Cvar_RegisterVariable(&r_nearclip);
7254 Cvar_RegisterVariable(&r_showbboxes);
7255 Cvar_RegisterVariable(&r_showsurfaces);
7256 Cvar_RegisterVariable(&r_showtris);
7257 Cvar_RegisterVariable(&r_shownormals);
7258 Cvar_RegisterVariable(&r_showlighting);
7259 Cvar_RegisterVariable(&r_showshadowvolumes);
7260 Cvar_RegisterVariable(&r_showcollisionbrushes);
7261 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7262 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7263 Cvar_RegisterVariable(&r_showdisabledepthtest);
7264 Cvar_RegisterVariable(&r_drawportals);
7265 Cvar_RegisterVariable(&r_drawentities);
7266 Cvar_RegisterVariable(&r_draw2d);
7267 Cvar_RegisterVariable(&r_drawworld);
7268 Cvar_RegisterVariable(&r_cullentities_trace);
7269 Cvar_RegisterVariable(&r_cullentities_trace_samples);
7270 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7271 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7272 Cvar_RegisterVariable(&r_cullentities_trace_delay);
7273 Cvar_RegisterVariable(&r_drawviewmodel);
7274 Cvar_RegisterVariable(&r_drawexteriormodel);
7275 Cvar_RegisterVariable(&r_speeds);
7276 Cvar_RegisterVariable(&r_fullbrights);
7277 Cvar_RegisterVariable(&r_wateralpha);
7278 Cvar_RegisterVariable(&r_dynamic);
7279 Cvar_RegisterVariable(&r_fakelight);
7280 Cvar_RegisterVariable(&r_fakelight_intensity);
7281 Cvar_RegisterVariable(&r_fullbright);
7282 Cvar_RegisterVariable(&r_shadows);
7283 Cvar_RegisterVariable(&r_shadows_darken);
7284 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7285 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7286 Cvar_RegisterVariable(&r_shadows_throwdistance);
7287 Cvar_RegisterVariable(&r_shadows_throwdirection);
7288 Cvar_RegisterVariable(&r_shadows_focus);
7289 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7290 Cvar_RegisterVariable(&r_q1bsp_skymasking);
7291 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7292 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7293 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7294 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7295 Cvar_RegisterVariable(&r_fog_exp2);
7296 Cvar_RegisterVariable(&r_drawfog);
7297 Cvar_RegisterVariable(&r_transparentdepthmasking);
7298 Cvar_RegisterVariable(&r_texture_dds_load);
7299 Cvar_RegisterVariable(&r_texture_dds_save);
7300 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7301 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7302 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7303 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7304 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7305 Cvar_RegisterVariable(&r_textureunits);
7306 Cvar_RegisterVariable(&gl_combine);
7307 Cvar_RegisterVariable(&r_glsl);
7308 Cvar_RegisterVariable(&r_glsl_deluxemapping);
7309 Cvar_RegisterVariable(&r_glsl_offsetmapping);
7310 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7311 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7312 Cvar_RegisterVariable(&r_glsl_postprocess);
7313 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7314 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7315 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7316 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7317 Cvar_RegisterVariable(&r_water);
7318 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7319 Cvar_RegisterVariable(&r_water_clippingplanebias);
7320 Cvar_RegisterVariable(&r_water_refractdistort);
7321 Cvar_RegisterVariable(&r_water_reflectdistort);
7322 Cvar_RegisterVariable(&r_water_scissormode);
7323 Cvar_RegisterVariable(&r_lerpsprites);
7324 Cvar_RegisterVariable(&r_lerpmodels);
7325 Cvar_RegisterVariable(&r_lerplightstyles);
7326 Cvar_RegisterVariable(&r_waterscroll);
7327 Cvar_RegisterVariable(&r_bloom);
7328 Cvar_RegisterVariable(&r_bloom_colorscale);
7329 Cvar_RegisterVariable(&r_bloom_brighten);
7330 Cvar_RegisterVariable(&r_bloom_blur);
7331 Cvar_RegisterVariable(&r_bloom_resolution);
7332 Cvar_RegisterVariable(&r_bloom_colorexponent);
7333 Cvar_RegisterVariable(&r_bloom_colorsubtract);
7334 Cvar_RegisterVariable(&r_hdr);
7335 Cvar_RegisterVariable(&r_hdr_scenebrightness);
7336 Cvar_RegisterVariable(&r_hdr_glowintensity);
7337 Cvar_RegisterVariable(&r_hdr_range);
7338 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7339 Cvar_RegisterVariable(&developer_texturelogging);
7340 Cvar_RegisterVariable(&gl_lightmaps);
7341 Cvar_RegisterVariable(&r_test);
7342 Cvar_RegisterVariable(&r_glsl_saturation);
7343 Cvar_RegisterVariable(&r_framedatasize);
7344 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7345 Cvar_SetValue("r_fullbrights", 0);
7346 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7348 Cvar_RegisterVariable(&r_track_sprites);
7349 Cvar_RegisterVariable(&r_track_sprites_flags);
7350 Cvar_RegisterVariable(&r_track_sprites_scalew);
7351 Cvar_RegisterVariable(&r_track_sprites_scaleh);
7352 Cvar_RegisterVariable(&r_overheadsprites_perspective);
7353 Cvar_RegisterVariable(&r_overheadsprites_pushback);
7356 extern void R_Textures_Init(void);
7357 extern void GL_Draw_Init(void);
7358 extern void GL_Main_Init(void);
7359 extern void R_Shadow_Init(void);
7360 extern void R_Sky_Init(void);
7361 extern void GL_Surf_Init(void);
7362 extern void R_Particles_Init(void);
7363 extern void R_Explosion_Init(void);
7364 extern void gl_backend_init(void);
7365 extern void Sbar_Init(void);
7366 extern void R_LightningBeams_Init(void);
7367 extern void Mod_RenderInit(void);
7368 extern void Font_Init(void);
7370 void Render_Init(void)
7383 R_LightningBeams_Init();
7392 extern char *ENGINE_EXTENSIONS;
7395 gl_renderer = (const char *)qglGetString(GL_RENDERER);
7396 gl_vendor = (const char *)qglGetString(GL_VENDOR);
7397 gl_version = (const char *)qglGetString(GL_VERSION);
7398 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7402 if (!gl_platformextensions)
7403 gl_platformextensions = "";
7405 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7406 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7407 Con_Printf("GL_VERSION: %s\n", gl_version);
7408 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7409 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7411 VID_CheckExtensions();
7413 // LordHavoc: report supported extensions
7414 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7416 // clear to black (loading plaque will be seen over this)
7417 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7420 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7424 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7426 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7429 p = r_refdef.view.frustum + i;
7434 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7438 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7442 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7446 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7450 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7454 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7458 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7462 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7470 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7474 for (i = 0;i < numplanes;i++)
7481 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7485 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7489 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7493 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7497 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7501 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7505 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7509 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7517 //==================================================================================
7519 // LordHavoc: this stores temporary data used within the same frame
7521 qboolean r_framedata_failed;
7522 static size_t r_framedata_size;
7523 static size_t r_framedata_current;
7524 static void *r_framedata_base;
7526 void R_FrameData_Reset(void)
7528 if (r_framedata_base)
7529 Mem_Free(r_framedata_base);
7530 r_framedata_base = NULL;
7531 r_framedata_size = 0;
7532 r_framedata_current = 0;
7533 r_framedata_failed = false;
7536 void R_FrameData_NewFrame(void)
7539 if (r_framedata_failed)
7540 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
7541 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7542 wantedsize = bound(65536, wantedsize, 128*1024*1024);
7543 if (r_framedata_size != wantedsize)
7545 r_framedata_size = wantedsize;
7546 if (r_framedata_base)
7547 Mem_Free(r_framedata_base);
7548 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
7550 r_framedata_current = 0;
7551 r_framedata_failed = false;
7554 void *R_FrameData_Alloc(size_t size)
7558 // align to 16 byte boundary
7559 size = (size + 15) & ~15;
7560 data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
7561 r_framedata_current += size;
7564 if (r_framedata_current > r_framedata_size)
7565 r_framedata_failed = true;
7567 // return NULL on everything after a failure
7568 if (r_framedata_failed)
7574 void *R_FrameData_Store(size_t size, void *data)
7576 void *d = R_FrameData_Alloc(size);
7578 memcpy(d, data, size);
7582 //==================================================================================
7584 // LordHavoc: animcache originally written by Echon, rewritten since then
7587 * Animation cache prevents re-generating mesh data for an animated model
7588 * multiple times in one frame for lighting, shadowing, reflections, etc.
7591 void R_AnimCache_Free(void)
7595 void R_AnimCache_ClearCache(void)
7598 entity_render_t *ent;
7600 for (i = 0;i < r_refdef.scene.numentities;i++)
7602 ent = r_refdef.scene.entities[i];
7603 ent->animcache_vertex3f = NULL;
7604 ent->animcache_normal3f = NULL;
7605 ent->animcache_svector3f = NULL;
7606 ent->animcache_tvector3f = NULL;
7607 ent->animcache_vertexposition = NULL;
7608 ent->animcache_vertexmesh = NULL;
7609 ent->animcache_vertexpositionbuffer = NULL;
7610 ent->animcache_vertexmeshbuffer = NULL;
7614 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7618 // identical memory layout, so no need to allocate...
7619 // this also provides the vertexposition structure to everything, e.g.
7620 // depth masked rendering currently uses it even if having separate
7622 // NOTE: get rid of this optimization if changing it to e.g. 4f
7623 ent->animcache_vertexposition = (r_vertexposition_t *)ent->animcache_vertex3f;
7626 // get rid of following uses of VERTEXPOSITION, change to the array:
7627 // R_DrawTextureSurfaceList_Sky if skyrendermasked
7628 // R_DrawSurface_TransparentCallback if r_transparentdepthmasking.integer
7629 // R_DrawTextureSurfaceList_DepthOnly
7630 // R_Q1BSP_DrawShadowMap
7632 switch(vid.renderpath)
7634 case RENDERPATH_GL20:
7635 case RENDERPATH_CGGL:
7636 // need the meshbuffers if !gl_mesh_separatearrays.integer
7637 if (gl_mesh_separatearrays.integer)
7640 case RENDERPATH_D3D9:
7641 case RENDERPATH_D3D10:
7642 case RENDERPATH_D3D11:
7643 // always need the meshbuffers
7645 case RENDERPATH_GL13:
7646 case RENDERPATH_GL11:
7647 // never need the meshbuffers
7651 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7652 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7654 if (!ent->animcache_vertexposition)
7655 ent->animcache_vertexposition = (r_vertexposition_t *)R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
7657 if (ent->animcache_vertexposition)
7660 for (i = 0;i < numvertices;i++)
7661 memcpy(ent->animcache_vertexposition[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7663 // TODO: upload vertex buffer?
7665 if (ent->animcache_vertexmesh)
7667 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7668 for (i = 0;i < numvertices;i++)
7669 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7670 if (ent->animcache_svector3f)
7671 for (i = 0;i < numvertices;i++)
7672 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7673 if (ent->animcache_tvector3f)
7674 for (i = 0;i < numvertices;i++)
7675 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7676 if (ent->animcache_normal3f)
7677 for (i = 0;i < numvertices;i++)
7678 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7679 // TODO: upload vertex buffer?
7683 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7685 dp_model_t *model = ent->model;
7687 // see if it's already cached this frame
7688 if (ent->animcache_vertex3f)
7690 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7691 if (wantnormals || wanttangents)
7693 if (ent->animcache_normal3f)
7694 wantnormals = false;
7695 if (ent->animcache_svector3f)
7696 wanttangents = false;
7697 if (wantnormals || wanttangents)
7699 numvertices = model->surfmesh.num_vertices;
7701 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7704 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7705 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7707 if (!r_framedata_failed)
7709 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7710 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7717 // see if this ent is worth caching
7718 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7720 // get some memory for this entity and generate mesh data
7721 numvertices = model->surfmesh.num_vertices;
7722 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7724 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7727 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7728 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7730 if (!r_framedata_failed)
7732 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7733 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7736 return !r_framedata_failed;
7739 void R_AnimCache_CacheVisibleEntities(void)
7742 qboolean wantnormals = true;
7743 qboolean wanttangents = !r_showsurfaces.integer;
7745 switch(vid.renderpath)
7747 case RENDERPATH_GL20:
7748 case RENDERPATH_CGGL:
7749 case RENDERPATH_D3D9:
7750 case RENDERPATH_D3D10:
7751 case RENDERPATH_D3D11:
7753 case RENDERPATH_GL13:
7754 case RENDERPATH_GL11:
7755 wanttangents = false;
7759 if (r_shownormals.integer)
7760 wanttangents = wantnormals = true;
7762 // TODO: thread this
7763 // NOTE: R_PrepareRTLights() also caches entities
7765 for (i = 0;i < r_refdef.scene.numentities;i++)
7766 if (r_refdef.viewcache.entityvisible[i])
7767 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7770 //==================================================================================
7772 static void R_View_UpdateEntityLighting (void)
7775 entity_render_t *ent;
7776 vec3_t tempdiffusenormal, avg;
7777 vec_t f, fa, fd, fdd;
7778 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7780 for (i = 0;i < r_refdef.scene.numentities;i++)
7782 ent = r_refdef.scene.entities[i];
7784 // skip unseen models
7785 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7789 if (ent->model && ent->model->brush.num_leafs)
7791 // TODO: use modellight for r_ambient settings on world?
7792 VectorSet(ent->modellight_ambient, 0, 0, 0);
7793 VectorSet(ent->modellight_diffuse, 0, 0, 0);
7794 VectorSet(ent->modellight_lightdir, 0, 0, 1);
7798 // fetch the lighting from the worldmodel data
7799 VectorClear(ent->modellight_ambient);
7800 VectorClear(ent->modellight_diffuse);
7801 VectorClear(tempdiffusenormal);
7802 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7805 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7806 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7807 if(ent->flags & RENDER_EQUALIZE)
7809 // first fix up ambient lighting...
7810 if(r_equalize_entities_minambient.value > 0)
7812 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7815 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7816 if(fa < r_equalize_entities_minambient.value * fd)
7819 // fa'/fd' = minambient
7820 // fa'+0.25*fd' = fa+0.25*fd
7822 // fa' = fd' * minambient
7823 // fd'*(0.25+minambient) = fa+0.25*fd
7825 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7826 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7828 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7829 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
7830 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7831 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7836 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7838 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
7839 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
7842 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
7843 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
7844 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7850 VectorSet(ent->modellight_ambient, 1, 1, 1);
7852 // move the light direction into modelspace coordinates for lighting code
7853 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7854 if(VectorLength2(ent->modellight_lightdir) == 0)
7855 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7856 VectorNormalize(ent->modellight_lightdir);
7860 #define MAX_LINEOFSIGHTTRACES 64
7862 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7865 vec3_t boxmins, boxmaxs;
7868 dp_model_t *model = r_refdef.scene.worldmodel;
7870 if (!model || !model->brush.TraceLineOfSight)
7873 // expand the box a little
7874 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7875 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7876 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7877 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7878 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7879 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7881 // return true if eye is inside enlarged box
7882 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7886 VectorCopy(eye, start);
7887 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7888 if (model->brush.TraceLineOfSight(model, start, end))
7891 // try various random positions
7892 for (i = 0;i < numsamples;i++)
7894 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7895 if (model->brush.TraceLineOfSight(model, start, end))
7903 static void R_View_UpdateEntityVisible (void)
7908 entity_render_t *ent;
7910 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7911 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7912 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
7913 : RENDER_EXTERIORMODEL;
7914 if (!r_drawviewmodel.integer)
7915 renderimask |= RENDER_VIEWMODEL;
7916 if (!r_drawexteriormodel.integer)
7917 renderimask |= RENDER_EXTERIORMODEL;
7918 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
7920 // worldmodel can check visibility
7921 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
7922 for (i = 0;i < r_refdef.scene.numentities;i++)
7924 ent = r_refdef.scene.entities[i];
7925 if (!(ent->flags & renderimask))
7926 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)))
7927 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))
7928 r_refdef.viewcache.entityvisible[i] = true;
7930 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
7931 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
7933 for (i = 0;i < r_refdef.scene.numentities;i++)
7935 ent = r_refdef.scene.entities[i];
7936 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
7938 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
7940 continue; // temp entities do pvs only
7941 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
7942 ent->last_trace_visibility = realtime;
7943 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
7944 r_refdef.viewcache.entityvisible[i] = 0;
7951 // no worldmodel or it can't check visibility
7952 for (i = 0;i < r_refdef.scene.numentities;i++)
7954 ent = r_refdef.scene.entities[i];
7955 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));
7960 /// only used if skyrendermasked, and normally returns false
7961 int R_DrawBrushModelsSky (void)
7964 entity_render_t *ent;
7967 for (i = 0;i < r_refdef.scene.numentities;i++)
7969 if (!r_refdef.viewcache.entityvisible[i])
7971 ent = r_refdef.scene.entities[i];
7972 if (!ent->model || !ent->model->DrawSky)
7974 ent->model->DrawSky(ent);
7980 static void R_DrawNoModel(entity_render_t *ent);
7981 static void R_DrawModels(void)
7984 entity_render_t *ent;
7986 for (i = 0;i < r_refdef.scene.numentities;i++)
7988 if (!r_refdef.viewcache.entityvisible[i])
7990 ent = r_refdef.scene.entities[i];
7991 r_refdef.stats.entities++;
7992 if (ent->model && ent->model->Draw != NULL)
7993 ent->model->Draw(ent);
7999 static void R_DrawModelsDepth(void)
8002 entity_render_t *ent;
8004 for (i = 0;i < r_refdef.scene.numentities;i++)
8006 if (!r_refdef.viewcache.entityvisible[i])
8008 ent = r_refdef.scene.entities[i];
8009 if (ent->model && ent->model->DrawDepth != NULL)
8010 ent->model->DrawDepth(ent);
8014 static void R_DrawModelsDebug(void)
8017 entity_render_t *ent;
8019 for (i = 0;i < r_refdef.scene.numentities;i++)
8021 if (!r_refdef.viewcache.entityvisible[i])
8023 ent = r_refdef.scene.entities[i];
8024 if (ent->model && ent->model->DrawDebug != NULL)
8025 ent->model->DrawDebug(ent);
8029 static void R_DrawModelsAddWaterPlanes(void)
8032 entity_render_t *ent;
8034 for (i = 0;i < r_refdef.scene.numentities;i++)
8036 if (!r_refdef.viewcache.entityvisible[i])
8038 ent = r_refdef.scene.entities[i];
8039 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
8040 ent->model->DrawAddWaterPlanes(ent);
8044 static void R_View_SetFrustum(const int *scissor)
8047 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
8048 vec3_t forward, left, up, origin, v;
8052 // flipped x coordinates (because x points left here)
8053 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8054 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8056 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
8057 switch(vid.renderpath)
8059 case RENDERPATH_D3D9:
8060 case RENDERPATH_D3D10:
8061 case RENDERPATH_D3D11:
8062 // non-flipped y coordinates
8063 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8064 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8066 case RENDERPATH_GL11:
8067 case RENDERPATH_GL13:
8068 case RENDERPATH_GL20:
8069 case RENDERPATH_CGGL:
8070 // non-flipped y coordinates
8071 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8072 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8077 // we can't trust r_refdef.view.forward and friends in reflected scenes
8078 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
8081 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
8082 r_refdef.view.frustum[0].normal[1] = 0 - 0;
8083 r_refdef.view.frustum[0].normal[2] = -1 - 0;
8084 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
8085 r_refdef.view.frustum[1].normal[1] = 0 + 0;
8086 r_refdef.view.frustum[1].normal[2] = -1 + 0;
8087 r_refdef.view.frustum[2].normal[0] = 0 - 0;
8088 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
8089 r_refdef.view.frustum[2].normal[2] = -1 - 0;
8090 r_refdef.view.frustum[3].normal[0] = 0 + 0;
8091 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
8092 r_refdef.view.frustum[3].normal[2] = -1 + 0;
8096 zNear = r_refdef.nearclip;
8097 nudge = 1.0 - 1.0 / (1<<23);
8098 r_refdef.view.frustum[4].normal[0] = 0 - 0;
8099 r_refdef.view.frustum[4].normal[1] = 0 - 0;
8100 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
8101 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
8102 r_refdef.view.frustum[5].normal[0] = 0 + 0;
8103 r_refdef.view.frustum[5].normal[1] = 0 + 0;
8104 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
8105 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
8111 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8112 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8113 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8114 r_refdef.view.frustum[0].dist = m[15] - m[12];
8116 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8117 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8118 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8119 r_refdef.view.frustum[1].dist = m[15] + m[12];
8121 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8122 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8123 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8124 r_refdef.view.frustum[2].dist = m[15] - m[13];
8126 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8127 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8128 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8129 r_refdef.view.frustum[3].dist = m[15] + m[13];
8131 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8132 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8133 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8134 r_refdef.view.frustum[4].dist = m[15] - m[14];
8136 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8137 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8138 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8139 r_refdef.view.frustum[5].dist = m[15] + m[14];
8142 if (r_refdef.view.useperspective)
8144 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8145 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]);
8146 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]);
8147 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]);
8148 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]);
8150 // then the normals from the corners relative to origin
8151 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
8152 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
8153 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
8154 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
8156 // in a NORMAL view, forward cross left == up
8157 // in a REFLECTED view, forward cross left == down
8158 // so our cross products above need to be adjusted for a left handed coordinate system
8159 CrossProduct(forward, left, v);
8160 if(DotProduct(v, up) < 0)
8162 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
8163 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
8164 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
8165 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
8168 // Leaving those out was a mistake, those were in the old code, and they
8169 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8170 // I couldn't reproduce it after adding those normalizations. --blub
8171 VectorNormalize(r_refdef.view.frustum[0].normal);
8172 VectorNormalize(r_refdef.view.frustum[1].normal);
8173 VectorNormalize(r_refdef.view.frustum[2].normal);
8174 VectorNormalize(r_refdef.view.frustum[3].normal);
8176 // make the corners absolute
8177 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
8178 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
8179 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
8180 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
8183 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8185 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8186 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8187 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8188 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8189 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8193 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8194 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8195 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8196 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8197 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8198 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8199 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8200 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8201 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8202 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8204 r_refdef.view.numfrustumplanes = 5;
8206 if (r_refdef.view.useclipplane)
8208 r_refdef.view.numfrustumplanes = 6;
8209 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8212 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8213 PlaneClassify(r_refdef.view.frustum + i);
8215 // LordHavoc: note to all quake engine coders, Quake had a special case
8216 // for 90 degrees which assumed a square view (wrong), so I removed it,
8217 // Quake2 has it disabled as well.
8219 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8220 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8221 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8222 //PlaneClassify(&frustum[0]);
8224 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8225 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8226 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8227 //PlaneClassify(&frustum[1]);
8229 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8230 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8231 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8232 //PlaneClassify(&frustum[2]);
8234 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8235 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8236 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8237 //PlaneClassify(&frustum[3]);
8240 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8241 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8242 //PlaneClassify(&frustum[4]);
8245 void R_View_UpdateWithScissor(const int *myscissor)
8247 R_Main_ResizeViewCache();
8248 R_View_SetFrustum(myscissor);
8249 R_View_WorldVisibility(r_refdef.view.useclipplane);
8250 R_View_UpdateEntityVisible();
8251 R_View_UpdateEntityLighting();
8254 void R_View_Update(void)
8256 R_Main_ResizeViewCache();
8257 R_View_SetFrustum(NULL);
8258 R_View_WorldVisibility(r_refdef.view.useclipplane);
8259 R_View_UpdateEntityVisible();
8260 R_View_UpdateEntityLighting();
8263 void R_SetupView(qboolean allowwaterclippingplane)
8265 const float *customclipplane = NULL;
8267 if (r_refdef.view.useclipplane && allowwaterclippingplane)
8269 // LordHavoc: couldn't figure out how to make this approach the
8270 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8271 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8272 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8273 dist = r_refdef.view.clipplane.dist;
8274 plane[0] = r_refdef.view.clipplane.normal[0];
8275 plane[1] = r_refdef.view.clipplane.normal[1];
8276 plane[2] = r_refdef.view.clipplane.normal[2];
8278 customclipplane = plane;
8281 if (!r_refdef.view.useperspective)
8282 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);
8283 else if (vid.stencil && r_useinfinitefarclip.integer)
8284 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);
8286 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);
8287 R_SetViewport(&r_refdef.view.viewport);
8290 void R_EntityMatrix(const matrix4x4_t *matrix)
8292 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8294 gl_modelmatrixchanged = false;
8295 gl_modelmatrix = *matrix;
8296 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8297 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8298 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8299 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8301 switch(vid.renderpath)
8303 case RENDERPATH_D3D9:
8305 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8306 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8309 case RENDERPATH_D3D10:
8310 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8312 case RENDERPATH_D3D11:
8313 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8315 case RENDERPATH_GL20:
8316 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8317 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8318 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8320 case RENDERPATH_CGGL:
8323 if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8324 if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8325 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8328 case RENDERPATH_GL13:
8329 case RENDERPATH_GL11:
8330 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8336 void R_ResetViewRendering2D(void)
8338 r_viewport_t viewport;
8341 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8342 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);
8343 R_SetViewport(&viewport);
8344 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8345 GL_Color(1, 1, 1, 1);
8346 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8347 GL_BlendFunc(GL_ONE, GL_ZERO);
8348 GL_AlphaTest(false);
8349 GL_ScissorTest(false);
8350 GL_DepthMask(false);
8351 GL_DepthRange(0, 1);
8352 GL_DepthTest(false);
8353 GL_DepthFunc(GL_LEQUAL);
8354 R_EntityMatrix(&identitymatrix);
8355 R_Mesh_ResetTextureState();
8356 GL_PolygonOffset(0, 0);
8357 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8358 switch(vid.renderpath)
8360 case RENDERPATH_GL11:
8361 case RENDERPATH_GL13:
8362 case RENDERPATH_GL20:
8363 case RENDERPATH_CGGL:
8364 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8366 case RENDERPATH_D3D9:
8367 case RENDERPATH_D3D10:
8368 case RENDERPATH_D3D11:
8371 GL_CullFace(GL_NONE);
8374 void R_ResetViewRendering3D(void)
8379 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8380 GL_Color(1, 1, 1, 1);
8381 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8382 GL_BlendFunc(GL_ONE, GL_ZERO);
8383 GL_AlphaTest(false);
8384 GL_ScissorTest(true);
8386 GL_DepthRange(0, 1);
8388 GL_DepthFunc(GL_LEQUAL);
8389 R_EntityMatrix(&identitymatrix);
8390 R_Mesh_ResetTextureState();
8391 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8392 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8393 switch(vid.renderpath)
8395 case RENDERPATH_GL11:
8396 case RENDERPATH_GL13:
8397 case RENDERPATH_GL20:
8398 case RENDERPATH_CGGL:
8399 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8401 case RENDERPATH_D3D9:
8402 case RENDERPATH_D3D10:
8403 case RENDERPATH_D3D11:
8406 GL_CullFace(r_refdef.view.cullface_back);
8411 R_RenderView_UpdateViewVectors
8414 static void R_RenderView_UpdateViewVectors(void)
8416 // break apart the view matrix into vectors for various purposes
8417 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8418 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8419 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8420 VectorNegate(r_refdef.view.left, r_refdef.view.right);
8421 // make an inverted copy of the view matrix for tracking sprites
8422 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8425 void R_RenderScene(void);
8426 void R_RenderWaterPlanes(void);
8428 static void R_Water_StartFrame(void)
8431 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8432 r_waterstate_waterplane_t *p;
8434 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8437 switch(vid.renderpath)
8439 case RENDERPATH_GL20:
8440 case RENDERPATH_CGGL:
8441 case RENDERPATH_D3D9:
8442 case RENDERPATH_D3D10:
8443 case RENDERPATH_D3D11:
8445 case RENDERPATH_GL13:
8446 case RENDERPATH_GL11:
8450 // set waterwidth and waterheight to the water resolution that will be
8451 // used (often less than the screen resolution for faster rendering)
8452 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8453 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8455 // calculate desired texture sizes
8456 // can't use water if the card does not support the texture size
8457 if (!r_water.integer || r_showsurfaces.integer)
8458 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8459 else if (vid.support.arb_texture_non_power_of_two)
8461 texturewidth = waterwidth;
8462 textureheight = waterheight;
8463 camerawidth = waterwidth;
8464 cameraheight = waterheight;
8468 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
8469 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
8470 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
8471 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
8474 // allocate textures as needed
8475 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8477 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8478 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8480 if (p->texture_refraction)
8481 R_FreeTexture(p->texture_refraction);
8482 p->texture_refraction = NULL;
8483 if (p->texture_reflection)
8484 R_FreeTexture(p->texture_reflection);
8485 p->texture_reflection = NULL;
8486 if (p->texture_camera)
8487 R_FreeTexture(p->texture_camera);
8488 p->texture_camera = NULL;
8490 memset(&r_waterstate, 0, sizeof(r_waterstate));
8491 r_waterstate.texturewidth = texturewidth;
8492 r_waterstate.textureheight = textureheight;
8493 r_waterstate.camerawidth = camerawidth;
8494 r_waterstate.cameraheight = cameraheight;
8497 if (r_waterstate.texturewidth)
8499 r_waterstate.enabled = true;
8501 // when doing a reduced render (HDR) we want to use a smaller area
8502 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8503 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8505 // set up variables that will be used in shader setup
8506 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8507 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8508 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8509 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8512 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8513 r_waterstate.numwaterplanes = 0;
8516 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8518 int triangleindex, planeindex;
8524 r_waterstate_waterplane_t *p;
8525 texture_t *t = R_GetCurrentTexture(surface->texture);
8527 // just use the first triangle with a valid normal for any decisions
8528 VectorClear(normal);
8529 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8531 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8532 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8533 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8534 TriangleNormal(vert[0], vert[1], vert[2], normal);
8535 if (VectorLength2(normal) >= 0.001)
8539 VectorCopy(normal, plane.normal);
8540 VectorNormalize(plane.normal);
8541 plane.dist = DotProduct(vert[0], plane.normal);
8542 PlaneClassify(&plane);
8543 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8545 // skip backfaces (except if nocullface is set)
8546 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8548 VectorNegate(plane.normal, plane.normal);
8550 PlaneClassify(&plane);
8554 // find a matching plane if there is one
8555 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8556 if(p->camera_entity == t->camera_entity)
8557 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8559 if (planeindex >= r_waterstate.maxwaterplanes)
8560 return; // nothing we can do, out of planes
8562 // if this triangle does not fit any known plane rendered this frame, add one
8563 if (planeindex >= r_waterstate.numwaterplanes)
8565 // store the new plane
8566 r_waterstate.numwaterplanes++;
8568 // clear materialflags and pvs
8569 p->materialflags = 0;
8570 p->pvsvalid = false;
8571 p->camera_entity = t->camera_entity;
8572 VectorCopy(surface->mins, p->mins);
8573 VectorCopy(surface->maxs, p->maxs);
8578 p->mins[0] = min(p->mins[0], surface->mins[0]);
8579 p->mins[1] = min(p->mins[1], surface->mins[1]);
8580 p->mins[2] = min(p->mins[2], surface->mins[2]);
8581 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8582 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8583 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8585 // merge this surface's materialflags into the waterplane
8586 p->materialflags |= t->currentmaterialflags;
8587 if(!(p->materialflags & MATERIALFLAG_CAMERA))
8589 // merge this surface's PVS into the waterplane
8590 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8591 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8592 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8594 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8600 static void R_Water_ProcessPlanes(void)
8603 r_refdef_view_t originalview;
8604 r_refdef_view_t myview;
8606 r_waterstate_waterplane_t *p;
8609 originalview = r_refdef.view;
8611 // make sure enough textures are allocated
8612 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8614 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8616 if (!p->texture_refraction)
8617 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
8618 if (!p->texture_refraction)
8621 else if (p->materialflags & MATERIALFLAG_CAMERA)
8623 if (!p->texture_camera)
8624 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_waterstate.camerawidth, r_waterstate.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
8625 if (!p->texture_camera)
8629 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8631 if (!p->texture_reflection)
8632 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
8633 if (!p->texture_reflection)
8639 r_refdef.view = originalview;
8640 r_refdef.view.showdebug = false;
8641 r_refdef.view.width = r_waterstate.waterwidth;
8642 r_refdef.view.height = r_waterstate.waterheight;
8643 r_refdef.view.useclipplane = true;
8644 myview = r_refdef.view;
8645 r_waterstate.renderingscene = true;
8646 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8648 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8650 r_refdef.view = myview;
8651 if(r_water_scissormode.integer)
8654 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8655 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8658 // render reflected scene and copy into texture
8659 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8660 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8661 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8662 r_refdef.view.clipplane = p->plane;
8664 // reverse the cullface settings for this render
8665 r_refdef.view.cullface_front = GL_FRONT;
8666 r_refdef.view.cullface_back = GL_BACK;
8667 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8669 r_refdef.view.usecustompvs = true;
8671 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8673 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8676 R_ResetViewRendering3D();
8677 R_ClearScreen(r_refdef.fogenabled);
8678 if(r_water_scissormode.integer & 2)
8679 R_View_UpdateWithScissor(myscissor);
8682 if(r_water_scissormode.integer & 1)
8683 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8686 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);
8689 // render the normal view scene and copy into texture
8690 // (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)
8691 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8693 r_refdef.view = myview;
8694 if(r_water_scissormode.integer)
8697 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8698 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8701 r_waterstate.renderingrefraction = true;
8703 r_refdef.view.clipplane = p->plane;
8704 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8705 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8707 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8709 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8710 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8711 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8712 R_RenderView_UpdateViewVectors();
8713 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8715 r_refdef.view.usecustompvs = true;
8716 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);
8720 PlaneClassify(&r_refdef.view.clipplane);
8722 R_ResetViewRendering3D();
8723 R_ClearScreen(r_refdef.fogenabled);
8724 if(r_water_scissormode.integer & 2)
8725 R_View_UpdateWithScissor(myscissor);
8728 if(r_water_scissormode.integer & 1)
8729 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8732 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);
8733 r_waterstate.renderingrefraction = false;
8735 else if (p->materialflags & MATERIALFLAG_CAMERA)
8737 r_refdef.view = myview;
8739 r_refdef.view.clipplane = p->plane;
8740 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8741 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8743 r_refdef.view.width = r_waterstate.camerawidth;
8744 r_refdef.view.height = r_waterstate.cameraheight;
8745 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8746 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8748 if(p->camera_entity)
8750 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8751 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8754 // note: all of the view is used for displaying... so
8755 // there is no use in scissoring
8757 // reverse the cullface settings for this render
8758 r_refdef.view.cullface_front = GL_FRONT;
8759 r_refdef.view.cullface_back = GL_BACK;
8760 // also reverse the view matrix
8761 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
8762 R_RenderView_UpdateViewVectors();
8763 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8765 r_refdef.view.usecustompvs = true;
8766 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);
8769 // camera needs no clipplane
8770 r_refdef.view.useclipplane = false;
8772 PlaneClassify(&r_refdef.view.clipplane);
8774 R_ResetViewRendering3D();
8775 R_ClearScreen(r_refdef.fogenabled);
8779 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);
8780 r_waterstate.renderingrefraction = false;
8784 r_waterstate.renderingscene = false;
8785 r_refdef.view = originalview;
8786 R_ResetViewRendering3D();
8787 R_ClearScreen(r_refdef.fogenabled);
8791 r_refdef.view = originalview;
8792 r_waterstate.renderingscene = false;
8793 Cvar_SetValueQuick(&r_water, 0);
8794 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
8798 void R_Bloom_StartFrame(void)
8800 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8802 switch(vid.renderpath)
8804 case RENDERPATH_GL20:
8805 case RENDERPATH_CGGL:
8806 case RENDERPATH_D3D9:
8807 case RENDERPATH_D3D10:
8808 case RENDERPATH_D3D11:
8810 case RENDERPATH_GL13:
8811 case RENDERPATH_GL11:
8815 // set bloomwidth and bloomheight to the bloom resolution that will be
8816 // used (often less than the screen resolution for faster rendering)
8817 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8818 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8819 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8820 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8821 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8823 // calculate desired texture sizes
8824 if (vid.support.arb_texture_non_power_of_two)
8826 screentexturewidth = r_refdef.view.width;
8827 screentextureheight = r_refdef.view.height;
8828 bloomtexturewidth = r_bloomstate.bloomwidth;
8829 bloomtextureheight = r_bloomstate.bloomheight;
8833 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
8834 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
8835 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
8836 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
8839 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))
8841 Cvar_SetValueQuick(&r_hdr, 0);
8842 Cvar_SetValueQuick(&r_bloom, 0);
8843 Cvar_SetValueQuick(&r_motionblur, 0);
8844 Cvar_SetValueQuick(&r_damageblur, 0);
8847 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)))
8848 screentexturewidth = screentextureheight = 0;
8849 if (!r_hdr.integer && !r_bloom.integer)
8850 bloomtexturewidth = bloomtextureheight = 0;
8852 // allocate textures as needed
8853 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8855 if (r_bloomstate.texture_screen)
8856 R_FreeTexture(r_bloomstate.texture_screen);
8857 r_bloomstate.texture_screen = NULL;
8858 r_bloomstate.screentexturewidth = screentexturewidth;
8859 r_bloomstate.screentextureheight = screentextureheight;
8860 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8861 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCENEAREST | TEXF_CLAMP, -1, NULL);
8863 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8865 if (r_bloomstate.texture_bloom)
8866 R_FreeTexture(r_bloomstate.texture_bloom);
8867 r_bloomstate.texture_bloom = NULL;
8868 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8869 r_bloomstate.bloomtextureheight = bloomtextureheight;
8870 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8871 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
8874 // when doing a reduced render (HDR) we want to use a smaller area
8875 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8876 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8877 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8878 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8879 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8881 // set up a texcoord array for the full resolution screen image
8882 // (we have to keep this around to copy back during final render)
8883 r_bloomstate.screentexcoord2f[0] = 0;
8884 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
8885 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
8886 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
8887 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
8888 r_bloomstate.screentexcoord2f[5] = 0;
8889 r_bloomstate.screentexcoord2f[6] = 0;
8890 r_bloomstate.screentexcoord2f[7] = 0;
8892 // set up a texcoord array for the reduced resolution bloom image
8893 // (which will be additive blended over the screen image)
8894 r_bloomstate.bloomtexcoord2f[0] = 0;
8895 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8896 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8897 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8898 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8899 r_bloomstate.bloomtexcoord2f[5] = 0;
8900 r_bloomstate.bloomtexcoord2f[6] = 0;
8901 r_bloomstate.bloomtexcoord2f[7] = 0;
8903 switch(vid.renderpath)
8905 case RENDERPATH_GL11:
8906 case RENDERPATH_GL13:
8907 case RENDERPATH_GL20:
8908 case RENDERPATH_CGGL:
8910 case RENDERPATH_D3D9:
8911 case RENDERPATH_D3D10:
8912 case RENDERPATH_D3D11:
8915 for (i = 0;i < 4;i++)
8917 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
8918 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
8919 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
8920 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
8926 if (r_hdr.integer || r_bloom.integer)
8928 r_bloomstate.enabled = true;
8929 r_bloomstate.hdr = r_hdr.integer != 0;
8932 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);
8935 void R_Bloom_CopyBloomTexture(float colorscale)
8937 r_refdef.stats.bloom++;
8939 // scale down screen texture to the bloom texture size
8941 R_SetViewport(&r_bloomstate.viewport);
8942 GL_BlendFunc(GL_ONE, GL_ZERO);
8943 GL_Color(colorscale, colorscale, colorscale, 1);
8944 // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
8945 switch(vid.renderpath)
8947 case RENDERPATH_GL11:
8948 case RENDERPATH_GL13:
8949 case RENDERPATH_GL20:
8950 case RENDERPATH_CGGL:
8951 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8953 case RENDERPATH_D3D9:
8954 case RENDERPATH_D3D10:
8955 case RENDERPATH_D3D11:
8956 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8959 // TODO: do boxfilter scale-down in shader?
8960 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8961 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8962 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8964 // we now have a bloom image in the framebuffer
8965 // copy it into the bloom image texture for later processing
8966 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);
8967 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8970 void R_Bloom_CopyHDRTexture(void)
8972 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);
8973 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8976 void R_Bloom_MakeTexture(void)
8979 float xoffset, yoffset, r, brighten;
8981 r_refdef.stats.bloom++;
8983 R_ResetViewRendering2D();
8985 // we have a bloom image in the framebuffer
8987 R_SetViewport(&r_bloomstate.viewport);
8989 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
8992 r = bound(0, r_bloom_colorexponent.value / x, 1);
8993 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
8995 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
8996 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8997 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8998 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9000 // copy the vertically blurred bloom view to a texture
9001 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);
9002 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9005 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
9006 brighten = r_bloom_brighten.value;
9008 brighten *= r_hdr_range.value;
9009 brighten = sqrt(brighten);
9011 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
9012 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9014 for (dir = 0;dir < 2;dir++)
9016 // blend on at multiple vertical offsets to achieve a vertical blur
9017 // TODO: do offset blends using GLSL
9018 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
9019 GL_BlendFunc(GL_ONE, GL_ZERO);
9020 for (x = -range;x <= range;x++)
9022 if (!dir){xoffset = 0;yoffset = x;}
9023 else {xoffset = x;yoffset = 0;}
9024 xoffset /= (float)r_bloomstate.bloomtexturewidth;
9025 yoffset /= (float)r_bloomstate.bloomtextureheight;
9026 // compute a texcoord array with the specified x and y offset
9027 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
9028 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9029 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9030 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9031 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9032 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
9033 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
9034 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
9035 // this r value looks like a 'dot' particle, fading sharply to
9036 // black at the edges
9037 // (probably not realistic but looks good enough)
9038 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
9039 //r = brighten/(range*2+1);
9040 r = brighten / (range * 2 + 1);
9042 r *= (1 - x*x/(float)(range*range));
9043 GL_Color(r, r, r, 1);
9044 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
9045 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9046 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9047 GL_BlendFunc(GL_ONE, GL_ONE);
9050 // copy the vertically blurred bloom view to a texture
9051 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);
9052 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9056 void R_HDR_RenderBloomTexture(void)
9058 int oldwidth, oldheight;
9059 float oldcolorscale;
9061 oldcolorscale = r_refdef.view.colorscale;
9062 oldwidth = r_refdef.view.width;
9063 oldheight = r_refdef.view.height;
9064 r_refdef.view.width = r_bloomstate.bloomwidth;
9065 r_refdef.view.height = r_bloomstate.bloomheight;
9067 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
9068 // TODO: add exposure compensation features
9069 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
9071 r_refdef.view.showdebug = false;
9072 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
9074 R_ResetViewRendering3D();
9076 R_ClearScreen(r_refdef.fogenabled);
9077 if (r_timereport_active)
9078 R_TimeReport("HDRclear");
9081 if (r_timereport_active)
9082 R_TimeReport("visibility");
9084 // only do secondary renders with HDR if r_hdr is 2 or higher
9085 r_waterstate.numwaterplanes = 0;
9086 if (r_waterstate.enabled && r_hdr.integer >= 2)
9087 R_RenderWaterPlanes();
9089 r_refdef.view.showdebug = true;
9091 r_waterstate.numwaterplanes = 0;
9093 R_ResetViewRendering2D();
9095 R_Bloom_CopyHDRTexture();
9096 R_Bloom_MakeTexture();
9098 // restore the view settings
9099 r_refdef.view.width = oldwidth;
9100 r_refdef.view.height = oldheight;
9101 r_refdef.view.colorscale = oldcolorscale;
9103 R_ResetViewRendering3D();
9105 R_ClearScreen(r_refdef.fogenabled);
9106 if (r_timereport_active)
9107 R_TimeReport("viewclear");
9110 static void R_BlendView(void)
9112 unsigned int permutation;
9113 float uservecs[4][4];
9115 switch (vid.renderpath)
9117 case RENDERPATH_GL20:
9118 case RENDERPATH_CGGL:
9119 case RENDERPATH_D3D9:
9120 case RENDERPATH_D3D10:
9121 case RENDERPATH_D3D11:
9123 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
9124 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
9125 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
9126 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
9127 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
9129 if (r_bloomstate.texture_screen)
9131 // make sure the buffer is available
9132 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
9134 R_ResetViewRendering2D();
9136 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
9138 // declare variables
9140 static float avgspeed;
9142 speed = VectorLength(cl.movement_velocity);
9144 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
9145 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
9147 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
9148 speed = bound(0, speed, 1);
9149 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
9151 // calculate values into a standard alpha
9152 cl.motionbluralpha = 1 - exp(-
9154 (r_motionblur.value * speed / 80)
9156 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
9159 max(0.0001, cl.time - cl.oldtime) // fps independent
9162 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
9163 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
9165 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
9167 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9168 GL_Color(1, 1, 1, cl.motionbluralpha);
9169 switch(vid.renderpath)
9171 case RENDERPATH_GL11:
9172 case RENDERPATH_GL13:
9173 case RENDERPATH_GL20:
9174 case RENDERPATH_CGGL:
9175 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9177 case RENDERPATH_D3D9:
9178 case RENDERPATH_D3D10:
9179 case RENDERPATH_D3D11:
9180 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9183 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9184 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9185 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9189 // copy view into the screen texture
9190 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);
9191 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9193 else if (!r_bloomstate.texture_bloom)
9195 // we may still have to do view tint...
9196 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9198 // apply a color tint to the whole view
9199 R_ResetViewRendering2D();
9200 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9201 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9202 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9203 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9204 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9206 break; // no screen processing, no bloom, skip it
9209 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9211 // render simple bloom effect
9212 // copy the screen and shrink it and darken it for the bloom process
9213 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9214 // make the bloom texture
9215 R_Bloom_MakeTexture();
9218 #if _MSC_VER >= 1400
9219 #define sscanf sscanf_s
9221 memset(uservecs, 0, sizeof(uservecs));
9222 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9223 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9224 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9225 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9227 R_ResetViewRendering2D();
9228 GL_Color(1, 1, 1, 1);
9229 GL_BlendFunc(GL_ONE, GL_ZERO);
9231 switch(vid.renderpath)
9233 case RENDERPATH_GL20:
9234 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9235 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9236 if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
9237 if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
9238 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
9239 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]);
9240 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9241 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]);
9242 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]);
9243 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]);
9244 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]);
9245 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
9246 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9247 if (r_glsl_permutation->loc_BloomColorSubtract >= 0) qglUniform4fARB(r_glsl_permutation->loc_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9249 case RENDERPATH_CGGL:
9251 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9252 R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9253 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_bloomstate.texture_screen);CHECKCGERROR
9254 if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_bloomstate.texture_bloom );CHECKCGERROR
9255 if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps );CHECKCGERROR
9256 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
9257 if (r_cg_permutation->fp_PixelSize ) cgGLSetParameter2f( r_cg_permutation->fp_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9258 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
9259 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
9260 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
9261 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
9262 if (r_cg_permutation->fp_Saturation ) cgGLSetParameter1f( r_cg_permutation->fp_Saturation , r_glsl_saturation.value);CHECKCGERROR
9263 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9264 if (r_cg_permutation->fp_BloomColorSubtract ) cgGLSetParameter4f(r_cg_permutation->fp_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9267 case RENDERPATH_D3D9:
9269 // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
9270 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9271 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9272 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
9273 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
9274 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
9275 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9276 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9277 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9278 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9279 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9280 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9281 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
9282 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9283 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9286 case RENDERPATH_D3D10:
9287 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9289 case RENDERPATH_D3D11:
9290 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9295 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9296 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9298 case RENDERPATH_GL13:
9299 case RENDERPATH_GL11:
9300 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9302 // apply a color tint to the whole view
9303 R_ResetViewRendering2D();
9304 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9305 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9306 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9307 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9308 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9314 matrix4x4_t r_waterscrollmatrix;
9316 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9318 if (r_refdef.fog_density)
9320 r_refdef.fogcolor[0] = r_refdef.fog_red;
9321 r_refdef.fogcolor[1] = r_refdef.fog_green;
9322 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9324 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9325 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9326 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9327 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9331 VectorCopy(r_refdef.fogcolor, fogvec);
9332 // color.rgb *= ContrastBoost * SceneBrightness;
9333 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9334 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9335 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9336 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9341 void R_UpdateVariables(void)
9345 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9347 r_refdef.farclip = r_farclip_base.value;
9348 if (r_refdef.scene.worldmodel)
9349 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9350 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9352 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9353 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9354 r_refdef.polygonfactor = 0;
9355 r_refdef.polygonoffset = 0;
9356 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9357 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9359 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9360 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9361 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
9362 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9363 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9364 if (FAKELIGHT_ENABLED)
9366 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
9368 if (r_showsurfaces.integer)
9370 r_refdef.scene.rtworld = false;
9371 r_refdef.scene.rtworldshadows = false;
9372 r_refdef.scene.rtdlight = false;
9373 r_refdef.scene.rtdlightshadows = false;
9374 r_refdef.lightmapintensity = 0;
9377 if (gamemode == GAME_NEHAHRA)
9379 if (gl_fogenable.integer)
9381 r_refdef.oldgl_fogenable = true;
9382 r_refdef.fog_density = gl_fogdensity.value;
9383 r_refdef.fog_red = gl_fogred.value;
9384 r_refdef.fog_green = gl_foggreen.value;
9385 r_refdef.fog_blue = gl_fogblue.value;
9386 r_refdef.fog_alpha = 1;
9387 r_refdef.fog_start = 0;
9388 r_refdef.fog_end = gl_skyclip.value;
9389 r_refdef.fog_height = 1<<30;
9390 r_refdef.fog_fadedepth = 128;
9392 else if (r_refdef.oldgl_fogenable)
9394 r_refdef.oldgl_fogenable = false;
9395 r_refdef.fog_density = 0;
9396 r_refdef.fog_red = 0;
9397 r_refdef.fog_green = 0;
9398 r_refdef.fog_blue = 0;
9399 r_refdef.fog_alpha = 0;
9400 r_refdef.fog_start = 0;
9401 r_refdef.fog_end = 0;
9402 r_refdef.fog_height = 1<<30;
9403 r_refdef.fog_fadedepth = 128;
9407 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9408 r_refdef.fog_start = max(0, r_refdef.fog_start);
9409 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9411 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9413 if (r_refdef.fog_density && r_drawfog.integer)
9415 r_refdef.fogenabled = true;
9416 // this is the point where the fog reaches 0.9986 alpha, which we
9417 // consider a good enough cutoff point for the texture
9418 // (0.9986 * 256 == 255.6)
9419 if (r_fog_exp2.integer)
9420 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9422 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9423 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9424 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9425 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9426 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9427 R_BuildFogHeightTexture();
9428 // fog color was already set
9429 // update the fog texture
9430 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)
9431 R_BuildFogTexture();
9432 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9433 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9436 r_refdef.fogenabled = false;
9438 switch(vid.renderpath)
9440 case RENDERPATH_GL20:
9441 case RENDERPATH_CGGL:
9442 case RENDERPATH_D3D9:
9443 case RENDERPATH_D3D10:
9444 case RENDERPATH_D3D11:
9445 if(v_glslgamma.integer && !vid_gammatables_trivial)
9447 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9449 // build GLSL gamma texture
9450 #define RAMPWIDTH 256
9451 unsigned short ramp[RAMPWIDTH * 3];
9452 unsigned char rampbgr[RAMPWIDTH][4];
9455 r_texture_gammaramps_serial = vid_gammatables_serial;
9457 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9458 for(i = 0; i < RAMPWIDTH; ++i)
9460 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9461 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9462 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9465 if (r_texture_gammaramps)
9467 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9471 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9477 // remove GLSL gamma texture
9480 case RENDERPATH_GL13:
9481 case RENDERPATH_GL11:
9486 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9487 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9493 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9494 if( scenetype != r_currentscenetype ) {
9495 // store the old scenetype
9496 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9497 r_currentscenetype = scenetype;
9498 // move in the new scene
9499 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9508 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9510 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9511 if( scenetype == r_currentscenetype ) {
9512 return &r_refdef.scene;
9514 return &r_scenes_store[ scenetype ];
9523 void R_RenderView(void)
9525 if (r_timereport_active)
9526 R_TimeReport("start");
9527 r_textureframe++; // used only by R_GetCurrentTexture
9528 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9530 if (!r_drawentities.integer)
9531 r_refdef.scene.numentities = 0;
9533 R_AnimCache_ClearCache();
9534 R_FrameData_NewFrame();
9536 if (r_refdef.view.isoverlay)
9538 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9539 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9540 R_TimeReport("depthclear");
9542 r_refdef.view.showdebug = false;
9544 r_waterstate.enabled = false;
9545 r_waterstate.numwaterplanes = 0;
9553 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9554 return; //Host_Error ("R_RenderView: NULL worldmodel");
9556 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9558 R_RenderView_UpdateViewVectors();
9560 R_Shadow_UpdateWorldLightSelection();
9562 R_Bloom_StartFrame();
9563 R_Water_StartFrame();
9566 if (r_timereport_active)
9567 R_TimeReport("viewsetup");
9569 R_ResetViewRendering3D();
9571 if (r_refdef.view.clear || r_refdef.fogenabled)
9573 R_ClearScreen(r_refdef.fogenabled);
9574 if (r_timereport_active)
9575 R_TimeReport("viewclear");
9577 r_refdef.view.clear = true;
9579 // this produces a bloom texture to be used in R_BlendView() later
9580 if (r_hdr.integer && r_bloomstate.bloomwidth)
9582 R_HDR_RenderBloomTexture();
9583 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9584 r_textureframe++; // used only by R_GetCurrentTexture
9587 r_refdef.view.showdebug = true;
9590 if (r_timereport_active)
9591 R_TimeReport("visibility");
9593 r_waterstate.numwaterplanes = 0;
9594 if (r_waterstate.enabled)
9595 R_RenderWaterPlanes();
9598 r_waterstate.numwaterplanes = 0;
9601 if (r_timereport_active)
9602 R_TimeReport("blendview");
9604 GL_Scissor(0, 0, vid.width, vid.height);
9605 GL_ScissorTest(false);
9610 void R_RenderWaterPlanes(void)
9612 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9614 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9615 if (r_timereport_active)
9616 R_TimeReport("waterworld");
9619 // don't let sound skip if going slow
9620 if (r_refdef.scene.extraupdate)
9623 R_DrawModelsAddWaterPlanes();
9624 if (r_timereport_active)
9625 R_TimeReport("watermodels");
9627 if (r_waterstate.numwaterplanes)
9629 R_Water_ProcessPlanes();
9630 if (r_timereport_active)
9631 R_TimeReport("waterscenes");
9635 extern void R_DrawLightningBeams (void);
9636 extern void VM_CL_AddPolygonsToMeshQueue (void);
9637 extern void R_DrawPortals (void);
9638 extern cvar_t cl_locs_show;
9639 static void R_DrawLocs(void);
9640 static void R_DrawEntityBBoxes(void);
9641 static void R_DrawModelDecals(void);
9642 extern void R_DrawModelShadows(void);
9643 extern void R_DrawModelShadowMaps(void);
9644 extern cvar_t cl_decals_newsystem;
9645 extern qboolean r_shadow_usingdeferredprepass;
9646 void R_RenderScene(void)
9648 qboolean shadowmapping = false;
9650 if (r_timereport_active)
9651 R_TimeReport("beginscene");
9653 r_refdef.stats.renders++;
9657 // don't let sound skip if going slow
9658 if (r_refdef.scene.extraupdate)
9661 R_MeshQueue_BeginScene();
9665 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);
9667 if (r_timereport_active)
9668 R_TimeReport("skystartframe");
9670 if (cl.csqc_vidvars.drawworld)
9672 // don't let sound skip if going slow
9673 if (r_refdef.scene.extraupdate)
9676 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9678 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9679 if (r_timereport_active)
9680 R_TimeReport("worldsky");
9683 if (R_DrawBrushModelsSky() && r_timereport_active)
9684 R_TimeReport("bmodelsky");
9686 if (skyrendermasked && skyrenderlater)
9688 // we have to force off the water clipping plane while rendering sky
9692 if (r_timereport_active)
9693 R_TimeReport("sky");
9697 R_AnimCache_CacheVisibleEntities();
9698 if (r_timereport_active)
9699 R_TimeReport("animation");
9701 R_Shadow_PrepareLights();
9702 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9703 R_Shadow_PrepareModelShadows();
9704 if (r_timereport_active)
9705 R_TimeReport("preparelights");
9707 if (R_Shadow_ShadowMappingEnabled())
9708 shadowmapping = true;
9710 if (r_shadow_usingdeferredprepass)
9711 R_Shadow_DrawPrepass();
9713 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9715 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9716 if (r_timereport_active)
9717 R_TimeReport("worlddepth");
9719 if (r_depthfirst.integer >= 2)
9721 R_DrawModelsDepth();
9722 if (r_timereport_active)
9723 R_TimeReport("modeldepth");
9726 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9728 R_DrawModelShadowMaps();
9729 R_ResetViewRendering3D();
9730 // don't let sound skip if going slow
9731 if (r_refdef.scene.extraupdate)
9735 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9737 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9738 if (r_timereport_active)
9739 R_TimeReport("world");
9742 // don't let sound skip if going slow
9743 if (r_refdef.scene.extraupdate)
9747 if (r_timereport_active)
9748 R_TimeReport("models");
9750 // don't let sound skip if going slow
9751 if (r_refdef.scene.extraupdate)
9754 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9756 R_DrawModelShadows();
9757 R_ResetViewRendering3D();
9758 // don't let sound skip if going slow
9759 if (r_refdef.scene.extraupdate)
9763 if (!r_shadow_usingdeferredprepass)
9765 R_Shadow_DrawLights();
9766 if (r_timereport_active)
9767 R_TimeReport("rtlights");
9770 // don't let sound skip if going slow
9771 if (r_refdef.scene.extraupdate)
9774 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9776 R_DrawModelShadows();
9777 R_ResetViewRendering3D();
9778 // don't let sound skip if going slow
9779 if (r_refdef.scene.extraupdate)
9783 if (cl.csqc_vidvars.drawworld)
9785 if (cl_decals_newsystem.integer)
9787 R_DrawModelDecals();
9788 if (r_timereport_active)
9789 R_TimeReport("modeldecals");
9794 if (r_timereport_active)
9795 R_TimeReport("decals");
9799 if (r_timereport_active)
9800 R_TimeReport("particles");
9803 if (r_timereport_active)
9804 R_TimeReport("explosions");
9806 R_DrawLightningBeams();
9807 if (r_timereport_active)
9808 R_TimeReport("lightning");
9811 VM_CL_AddPolygonsToMeshQueue();
9813 if (r_refdef.view.showdebug)
9815 if (cl_locs_show.integer)
9818 if (r_timereport_active)
9819 R_TimeReport("showlocs");
9822 if (r_drawportals.integer)
9825 if (r_timereport_active)
9826 R_TimeReport("portals");
9829 if (r_showbboxes.value > 0)
9831 R_DrawEntityBBoxes();
9832 if (r_timereport_active)
9833 R_TimeReport("bboxes");
9837 R_MeshQueue_RenderTransparent();
9838 if (r_timereport_active)
9839 R_TimeReport("drawtrans");
9841 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))
9843 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9844 if (r_timereport_active)
9845 R_TimeReport("worlddebug");
9846 R_DrawModelsDebug();
9847 if (r_timereport_active)
9848 R_TimeReport("modeldebug");
9851 if (cl.csqc_vidvars.drawworld)
9853 R_Shadow_DrawCoronas();
9854 if (r_timereport_active)
9855 R_TimeReport("coronas");
9860 GL_DepthTest(false);
9861 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9862 GL_Color(1, 1, 1, 1);
9863 qglBegin(GL_POLYGON);
9864 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
9865 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
9866 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
9867 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
9869 qglBegin(GL_POLYGON);
9870 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]);
9871 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]);
9872 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]);
9873 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]);
9875 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9879 // don't let sound skip if going slow
9880 if (r_refdef.scene.extraupdate)
9883 R_ResetViewRendering2D();
9886 static const unsigned short bboxelements[36] =
9896 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9899 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9901 RSurf_ActiveWorldEntity();
9903 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9904 GL_DepthMask(false);
9905 GL_DepthRange(0, 1);
9906 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9907 R_Mesh_ResetTextureState();
9909 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9910 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9911 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9912 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9913 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9914 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9915 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9916 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9917 R_FillColors(color4f, 8, cr, cg, cb, ca);
9918 if (r_refdef.fogenabled)
9920 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9922 f1 = RSurf_FogVertex(v);
9924 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9925 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9926 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9929 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
9930 R_Mesh_ResetTextureState();
9931 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9932 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
9935 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9939 prvm_edict_t *edict;
9940 prvm_prog_t *prog_save = prog;
9942 // this function draws bounding boxes of server entities
9946 GL_CullFace(GL_NONE);
9947 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9951 for (i = 0;i < numsurfaces;i++)
9953 edict = PRVM_EDICT_NUM(surfacelist[i]);
9954 switch ((int)edict->fields.server->solid)
9956 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
9957 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
9958 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
9959 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9960 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
9961 default: Vector4Set(color, 0, 0, 0, 0.50);break;
9963 color[3] *= r_showbboxes.value;
9964 color[3] = bound(0, color[3], 1);
9965 GL_DepthTest(!r_showdisabledepthtest.integer);
9966 GL_CullFace(r_refdef.view.cullface_front);
9967 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
9973 static void R_DrawEntityBBoxes(void)
9976 prvm_edict_t *edict;
9978 prvm_prog_t *prog_save = prog;
9980 // this function draws bounding boxes of server entities
9986 for (i = 0;i < prog->num_edicts;i++)
9988 edict = PRVM_EDICT_NUM(i);
9989 if (edict->priv.server->free)
9991 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
9992 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
9994 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
9996 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
9997 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
10003 static const int nomodelelement3i[24] =
10015 static const unsigned short nomodelelement3s[24] =
10027 static const float nomodelvertex3f[6*3] =
10037 static const float nomodelcolor4f[6*4] =
10039 0.0f, 0.0f, 0.5f, 1.0f,
10040 0.0f, 0.0f, 0.5f, 1.0f,
10041 0.0f, 0.5f, 0.0f, 1.0f,
10042 0.0f, 0.5f, 0.0f, 1.0f,
10043 0.5f, 0.0f, 0.0f, 1.0f,
10044 0.5f, 0.0f, 0.0f, 1.0f
10047 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10051 float color4f[6*4];
10053 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);
10055 // this is only called once per entity so numsurfaces is always 1, and
10056 // surfacelist is always {0}, so this code does not handle batches
10058 if (rsurface.ent_flags & RENDER_ADDITIVE)
10060 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
10061 GL_DepthMask(false);
10063 else if (rsurface.colormod[3] < 1)
10065 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10066 GL_DepthMask(false);
10070 GL_BlendFunc(GL_ONE, GL_ZERO);
10071 GL_DepthMask(true);
10073 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
10074 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
10075 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
10076 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
10077 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10078 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
10079 for (i = 0, c = color4f;i < 6;i++, c += 4)
10081 c[0] *= rsurface.colormod[0];
10082 c[1] *= rsurface.colormod[1];
10083 c[2] *= rsurface.colormod[2];
10084 c[3] *= rsurface.colormod[3];
10086 if (r_refdef.fogenabled)
10088 for (i = 0, c = color4f;i < 6;i++, c += 4)
10090 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
10092 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
10093 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
10094 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
10097 R_Mesh_ResetTextureState();
10098 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
10099 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
10102 void R_DrawNoModel(entity_render_t *ent)
10105 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
10106 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
10107 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
10109 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
10112 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
10114 vec3_t right1, right2, diff, normal;
10116 VectorSubtract (org2, org1, normal);
10118 // calculate 'right' vector for start
10119 VectorSubtract (r_refdef.view.origin, org1, diff);
10120 CrossProduct (normal, diff, right1);
10121 VectorNormalize (right1);
10123 // calculate 'right' vector for end
10124 VectorSubtract (r_refdef.view.origin, org2, diff);
10125 CrossProduct (normal, diff, right2);
10126 VectorNormalize (right2);
10128 vert[ 0] = org1[0] + width * right1[0];
10129 vert[ 1] = org1[1] + width * right1[1];
10130 vert[ 2] = org1[2] + width * right1[2];
10131 vert[ 3] = org1[0] - width * right1[0];
10132 vert[ 4] = org1[1] - width * right1[1];
10133 vert[ 5] = org1[2] - width * right1[2];
10134 vert[ 6] = org2[0] - width * right2[0];
10135 vert[ 7] = org2[1] - width * right2[1];
10136 vert[ 8] = org2[2] - width * right2[2];
10137 vert[ 9] = org2[0] + width * right2[0];
10138 vert[10] = org2[1] + width * right2[1];
10139 vert[11] = org2[2] + width * right2[2];
10142 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)
10144 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
10145 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
10146 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
10147 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
10148 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
10149 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
10150 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
10151 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
10152 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
10153 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
10154 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
10155 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
10158 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
10163 VectorSet(v, x, y, z);
10164 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
10165 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
10167 if (i == mesh->numvertices)
10169 if (mesh->numvertices < mesh->maxvertices)
10171 VectorCopy(v, vertex3f);
10172 mesh->numvertices++;
10174 return mesh->numvertices;
10180 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
10183 int *e, element[3];
10184 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10185 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10186 e = mesh->element3i + mesh->numtriangles * 3;
10187 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
10189 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
10190 if (mesh->numtriangles < mesh->maxtriangles)
10195 mesh->numtriangles++;
10197 element[1] = element[2];
10201 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
10204 int *e, element[3];
10205 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10206 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10207 e = mesh->element3i + mesh->numtriangles * 3;
10208 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10210 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10211 if (mesh->numtriangles < mesh->maxtriangles)
10216 mesh->numtriangles++;
10218 element[1] = element[2];
10222 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10223 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10225 int planenum, planenum2;
10228 mplane_t *plane, *plane2;
10230 double temppoints[2][256*3];
10231 // figure out how large a bounding box we need to properly compute this brush
10233 for (w = 0;w < numplanes;w++)
10234 maxdist = max(maxdist, fabs(planes[w].dist));
10235 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10236 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10237 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10241 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10242 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10244 if (planenum2 == planenum)
10246 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);
10249 if (tempnumpoints < 3)
10251 // generate elements forming a triangle fan for this polygon
10252 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10256 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)
10258 texturelayer_t *layer;
10259 layer = t->currentlayers + t->currentnumlayers++;
10260 layer->type = type;
10261 layer->depthmask = depthmask;
10262 layer->blendfunc1 = blendfunc1;
10263 layer->blendfunc2 = blendfunc2;
10264 layer->texture = texture;
10265 layer->texmatrix = *matrix;
10266 layer->color[0] = r;
10267 layer->color[1] = g;
10268 layer->color[2] = b;
10269 layer->color[3] = a;
10272 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10274 if(parms[0] == 0 && parms[1] == 0)
10276 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10277 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10282 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10285 index = parms[2] + r_refdef.scene.time * parms[3];
10286 index -= floor(index);
10287 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10290 case Q3WAVEFUNC_NONE:
10291 case Q3WAVEFUNC_NOISE:
10292 case Q3WAVEFUNC_COUNT:
10295 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10296 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10297 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10298 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10299 case Q3WAVEFUNC_TRIANGLE:
10301 f = index - floor(index);
10304 else if (index < 2)
10306 else if (index < 3)
10312 f = parms[0] + parms[1] * f;
10313 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10314 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10318 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10323 matrix4x4_t matrix, temp;
10324 switch(tcmod->tcmod)
10326 case Q3TCMOD_COUNT:
10328 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10329 matrix = r_waterscrollmatrix;
10331 matrix = identitymatrix;
10333 case Q3TCMOD_ENTITYTRANSLATE:
10334 // this is used in Q3 to allow the gamecode to control texcoord
10335 // scrolling on the entity, which is not supported in darkplaces yet.
10336 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10338 case Q3TCMOD_ROTATE:
10339 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10340 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10341 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10343 case Q3TCMOD_SCALE:
10344 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10346 case Q3TCMOD_SCROLL:
10347 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10349 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10350 w = (int) tcmod->parms[0];
10351 h = (int) tcmod->parms[1];
10352 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10354 idx = (int) floor(f * w * h);
10355 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10357 case Q3TCMOD_STRETCH:
10358 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10359 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10361 case Q3TCMOD_TRANSFORM:
10362 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
10363 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
10364 VectorSet(tcmat + 6, 0 , 0 , 1);
10365 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
10366 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10368 case Q3TCMOD_TURBULENT:
10369 // this is handled in the RSurf_PrepareVertices function
10370 matrix = identitymatrix;
10374 Matrix4x4_Concat(texmatrix, &matrix, &temp);
10377 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10379 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10380 char name[MAX_QPATH];
10381 skinframe_t *skinframe;
10382 unsigned char pixels[296*194];
10383 strlcpy(cache->name, skinname, sizeof(cache->name));
10384 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10385 if (developer_loading.integer)
10386 Con_Printf("loading %s\n", name);
10387 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10388 if (!skinframe || !skinframe->base)
10391 fs_offset_t filesize;
10393 f = FS_LoadFile(name, tempmempool, true, &filesize);
10396 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10397 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10401 cache->skinframe = skinframe;
10404 texture_t *R_GetCurrentTexture(texture_t *t)
10407 const entity_render_t *ent = rsurface.entity;
10408 dp_model_t *model = ent->model;
10409 q3shaderinfo_layer_tcmod_t *tcmod;
10411 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10412 return t->currentframe;
10413 t->update_lastrenderframe = r_textureframe;
10414 t->update_lastrenderentity = (void *)ent;
10416 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10417 t->camera_entity = ent->entitynumber;
10419 t->camera_entity = 0;
10421 // switch to an alternate material if this is a q1bsp animated material
10423 texture_t *texture = t;
10424 int s = rsurface.ent_skinnum;
10425 if ((unsigned int)s >= (unsigned int)model->numskins)
10427 if (model->skinscenes)
10429 if (model->skinscenes[s].framecount > 1)
10430 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10432 s = model->skinscenes[s].firstframe;
10435 t = t + s * model->num_surfaces;
10438 // use an alternate animation if the entity's frame is not 0,
10439 // and only if the texture has an alternate animation
10440 if (rsurface.ent_alttextures && t->anim_total[1])
10441 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10443 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10445 texture->currentframe = t;
10448 // update currentskinframe to be a qw skin or animation frame
10449 if (rsurface.ent_qwskin >= 0)
10451 i = rsurface.ent_qwskin;
10452 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10454 r_qwskincache_size = cl.maxclients;
10456 Mem_Free(r_qwskincache);
10457 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10459 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10460 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10461 t->currentskinframe = r_qwskincache[i].skinframe;
10462 if (t->currentskinframe == NULL)
10463 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10465 else if (t->numskinframes >= 2)
10466 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10467 if (t->backgroundnumskinframes >= 2)
10468 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10470 t->currentmaterialflags = t->basematerialflags;
10471 t->currentalpha = rsurface.colormod[3];
10472 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10473 t->currentalpha *= r_wateralpha.value;
10474 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10475 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10476 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10477 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10478 if (!(rsurface.ent_flags & RENDER_LIGHT))
10479 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10480 else if (FAKELIGHT_ENABLED)
10482 // no modellight if using fakelight for the map
10484 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10486 // pick a model lighting mode
10487 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10488 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10490 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10492 if (rsurface.ent_flags & RENDER_ADDITIVE)
10493 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10494 else if (t->currentalpha < 1)
10495 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10496 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10497 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10498 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10499 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10500 if (t->backgroundnumskinframes)
10501 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10502 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10504 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10505 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10508 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10509 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10510 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10512 // there is no tcmod
10513 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10515 t->currenttexmatrix = r_waterscrollmatrix;
10516 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10518 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10520 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10521 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10524 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10525 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10526 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10527 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10529 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10530 if (t->currentskinframe->qpixels)
10531 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10532 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10533 if (!t->basetexture)
10534 t->basetexture = r_texture_notexture;
10535 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10536 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10537 t->nmaptexture = t->currentskinframe->nmap;
10538 if (!t->nmaptexture)
10539 t->nmaptexture = r_texture_blanknormalmap;
10540 t->glosstexture = r_texture_black;
10541 t->glowtexture = t->currentskinframe->glow;
10542 t->fogtexture = t->currentskinframe->fog;
10543 t->reflectmasktexture = t->currentskinframe->reflect;
10544 if (t->backgroundnumskinframes)
10546 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10547 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10548 t->backgroundglosstexture = r_texture_black;
10549 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10550 if (!t->backgroundnmaptexture)
10551 t->backgroundnmaptexture = r_texture_blanknormalmap;
10555 t->backgroundbasetexture = r_texture_white;
10556 t->backgroundnmaptexture = r_texture_blanknormalmap;
10557 t->backgroundglosstexture = r_texture_black;
10558 t->backgroundglowtexture = NULL;
10560 t->specularpower = r_shadow_glossexponent.value;
10561 // TODO: store reference values for these in the texture?
10562 t->specularscale = 0;
10563 if (r_shadow_gloss.integer > 0)
10565 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10567 if (r_shadow_glossintensity.value > 0)
10569 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10570 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10571 t->specularscale = r_shadow_glossintensity.value;
10574 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10576 t->glosstexture = r_texture_white;
10577 t->backgroundglosstexture = r_texture_white;
10578 t->specularscale = r_shadow_gloss2intensity.value;
10579 t->specularpower = r_shadow_gloss2exponent.value;
10582 t->specularscale *= t->specularscalemod;
10583 t->specularpower *= t->specularpowermod;
10585 // lightmaps mode looks bad with dlights using actual texturing, so turn
10586 // off the colormap and glossmap, but leave the normalmap on as it still
10587 // accurately represents the shading involved
10588 if (gl_lightmaps.integer)
10590 t->basetexture = r_texture_grey128;
10591 t->pantstexture = r_texture_black;
10592 t->shirttexture = r_texture_black;
10593 t->nmaptexture = r_texture_blanknormalmap;
10594 t->glosstexture = r_texture_black;
10595 t->glowtexture = NULL;
10596 t->fogtexture = NULL;
10597 t->reflectmasktexture = NULL;
10598 t->backgroundbasetexture = NULL;
10599 t->backgroundnmaptexture = r_texture_blanknormalmap;
10600 t->backgroundglosstexture = r_texture_black;
10601 t->backgroundglowtexture = NULL;
10602 t->specularscale = 0;
10603 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10606 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10607 VectorClear(t->dlightcolor);
10608 t->currentnumlayers = 0;
10609 if (t->currentmaterialflags & MATERIALFLAG_WALL)
10611 int blendfunc1, blendfunc2;
10612 qboolean depthmask;
10613 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10615 blendfunc1 = GL_SRC_ALPHA;
10616 blendfunc2 = GL_ONE;
10618 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10620 blendfunc1 = GL_SRC_ALPHA;
10621 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10623 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10625 blendfunc1 = t->customblendfunc[0];
10626 blendfunc2 = t->customblendfunc[1];
10630 blendfunc1 = GL_ONE;
10631 blendfunc2 = GL_ZERO;
10633 // don't colormod evilblend textures
10634 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10635 VectorSet(t->lightmapcolor, 1, 1, 1);
10636 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10637 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10639 // fullbright is not affected by r_refdef.lightmapintensity
10640 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]);
10641 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10642 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]);
10643 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10644 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]);
10648 vec3_t ambientcolor;
10650 // set the color tint used for lights affecting this surface
10651 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10653 // q3bsp has no lightmap updates, so the lightstylevalue that
10654 // would normally be baked into the lightmap must be
10655 // applied to the color
10656 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10657 if (model->type == mod_brushq3)
10658 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10659 colorscale *= r_refdef.lightmapintensity;
10660 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10661 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10662 // basic lit geometry
10663 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]);
10664 // add pants/shirt if needed
10665 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10666 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]);
10667 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10668 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]);
10669 // now add ambient passes if needed
10670 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10672 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]);
10673 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10674 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]);
10675 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10676 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]);
10679 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10680 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]);
10681 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10683 // if this is opaque use alpha blend which will darken the earlier
10686 // if this is an alpha blended material, all the earlier passes
10687 // were darkened by fog already, so we only need to add the fog
10688 // color ontop through the fog mask texture
10690 // if this is an additive blended material, all the earlier passes
10691 // were darkened by fog already, and we should not add fog color
10692 // (because the background was not darkened, there is no fog color
10693 // that was lost behind it).
10694 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]);
10698 return t->currentframe;
10701 rsurfacestate_t rsurface;
10703 void R_Mesh_ResizeArrays(int newvertices)
10705 unsigned char *base;
10707 if (rsurface.array_size >= newvertices)
10709 if (rsurface.array_base)
10710 Mem_Free(rsurface.array_base);
10711 rsurface.array_size = (newvertices + 1023) & ~1023;
10713 size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10714 size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10715 size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10716 size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10717 size += rsurface.array_size * sizeof(float[3]);
10718 size += rsurface.array_size * sizeof(float[3]);
10719 size += rsurface.array_size * sizeof(float[3]);
10720 size += rsurface.array_size * sizeof(float[3]);
10721 size += rsurface.array_size * sizeof(float[3]);
10722 size += rsurface.array_size * sizeof(float[3]);
10723 size += rsurface.array_size * sizeof(float[3]);
10724 size += rsurface.array_size * sizeof(float[3]);
10725 size += rsurface.array_size * sizeof(float[4]);
10726 size += rsurface.array_size * sizeof(float[2]);
10727 size += rsurface.array_size * sizeof(float[2]);
10728 size += rsurface.array_size * sizeof(float[4]);
10729 size += rsurface.array_size * sizeof(int[3]);
10730 size += rsurface.array_size * sizeof(unsigned short[3]);
10731 rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
10732 rsurface.array_modelvertexmesh = (r_vertexmesh_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10733 rsurface.array_batchvertexmesh = (r_vertexmesh_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10734 rsurface.array_modelvertexposition = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10735 rsurface.array_batchvertexposition = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10736 rsurface.array_modelvertex3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10737 rsurface.array_modelsvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10738 rsurface.array_modeltvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10739 rsurface.array_modelnormal3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10740 rsurface.array_batchvertex3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10741 rsurface.array_batchsvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10742 rsurface.array_batchtvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10743 rsurface.array_batchnormal3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10744 rsurface.array_batchlightmapcolor4f = (float *)base;base += rsurface.array_size * sizeof(float[4]);
10745 rsurface.array_batchtexcoordtexture2f = (float *)base;base += rsurface.array_size * sizeof(float[2]);
10746 rsurface.array_batchtexcoordlightmap2f = (float *)base;base += rsurface.array_size * sizeof(float[2]);
10747 rsurface.array_passcolor4f = (float *)base;base += rsurface.array_size * sizeof(float[4]);
10748 rsurface.array_batchelement3i = (int *)base;base += rsurface.array_size * sizeof(int[3]);
10749 rsurface.array_batchelement3s = (unsigned short *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
10752 void RSurf_ActiveWorldEntity(void)
10754 dp_model_t *model = r_refdef.scene.worldmodel;
10755 //if (rsurface.entity == r_refdef.scene.worldentity)
10757 rsurface.entity = r_refdef.scene.worldentity;
10758 rsurface.skeleton = NULL;
10759 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10760 rsurface.ent_skinnum = 0;
10761 rsurface.ent_qwskin = -1;
10762 rsurface.ent_shadertime = 0;
10763 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10764 if (rsurface.array_size < model->surfmesh.num_vertices)
10765 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10766 rsurface.matrix = identitymatrix;
10767 rsurface.inversematrix = identitymatrix;
10768 rsurface.matrixscale = 1;
10769 rsurface.inversematrixscale = 1;
10770 R_EntityMatrix(&identitymatrix);
10771 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10772 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10773 rsurface.fograngerecip = r_refdef.fograngerecip;
10774 rsurface.fogheightfade = r_refdef.fogheightfade;
10775 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10776 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10777 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10778 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10779 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10780 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10781 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10782 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10783 rsurface.colormod[3] = 1;
10784 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);
10785 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10786 rsurface.frameblend[0].lerp = 1;
10787 rsurface.ent_alttextures = false;
10788 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10789 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10790 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
10791 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10792 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10793 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10794 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10795 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10796 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10797 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10798 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10799 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
10800 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10801 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10802 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
10803 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10804 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10805 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
10806 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10807 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10808 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
10809 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10810 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10811 rsurface.modelelement3i = model->surfmesh.data_element3i;
10812 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10813 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10814 rsurface.modelelement3s = model->surfmesh.data_element3s;
10815 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10816 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10817 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10818 rsurface.modelnumvertices = model->surfmesh.num_vertices;
10819 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10820 rsurface.modelsurfaces = model->data_surfaces;
10821 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10822 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10823 rsurface.modelvertexposition = model->surfmesh.vertexposition;
10824 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10825 rsurface.modelgeneratedvertex = false;
10826 rsurface.batchgeneratedvertex = false;
10827 rsurface.batchfirstvertex = 0;
10828 rsurface.batchnumvertices = 0;
10829 rsurface.batchfirsttriangle = 0;
10830 rsurface.batchnumtriangles = 0;
10831 rsurface.batchvertex3f = NULL;
10832 rsurface.batchvertex3f_vertexbuffer = NULL;
10833 rsurface.batchvertex3f_bufferoffset = 0;
10834 rsurface.batchsvector3f = NULL;
10835 rsurface.batchsvector3f_vertexbuffer = NULL;
10836 rsurface.batchsvector3f_bufferoffset = 0;
10837 rsurface.batchtvector3f = NULL;
10838 rsurface.batchtvector3f_vertexbuffer = NULL;
10839 rsurface.batchtvector3f_bufferoffset = 0;
10840 rsurface.batchnormal3f = NULL;
10841 rsurface.batchnormal3f_vertexbuffer = NULL;
10842 rsurface.batchnormal3f_bufferoffset = 0;
10843 rsurface.batchlightmapcolor4f = NULL;
10844 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10845 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10846 rsurface.batchtexcoordtexture2f = NULL;
10847 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10848 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10849 rsurface.batchtexcoordlightmap2f = NULL;
10850 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10851 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10852 rsurface.batchvertexmesh = NULL;
10853 rsurface.batchvertexmeshbuffer = NULL;
10854 rsurface.batchvertexposition = NULL;
10855 rsurface.batchvertexpositionbuffer = NULL;
10856 rsurface.batchelement3i = NULL;
10857 rsurface.batchelement3i_indexbuffer = NULL;
10858 rsurface.batchelement3i_bufferoffset = 0;
10859 rsurface.batchelement3s = NULL;
10860 rsurface.batchelement3s_indexbuffer = NULL;
10861 rsurface.batchelement3s_bufferoffset = 0;
10862 rsurface.passcolor4f = NULL;
10863 rsurface.passcolor4f_vertexbuffer = NULL;
10864 rsurface.passcolor4f_bufferoffset = 0;
10867 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10869 dp_model_t *model = ent->model;
10870 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10872 rsurface.entity = (entity_render_t *)ent;
10873 rsurface.skeleton = ent->skeleton;
10874 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10875 rsurface.ent_skinnum = ent->skinnum;
10876 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;
10877 rsurface.ent_shadertime = ent->shadertime;
10878 rsurface.ent_flags = ent->flags;
10879 if (rsurface.array_size < model->surfmesh.num_vertices)
10880 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10881 rsurface.matrix = ent->matrix;
10882 rsurface.inversematrix = ent->inversematrix;
10883 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10884 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10885 R_EntityMatrix(&rsurface.matrix);
10886 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10887 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10888 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10889 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10890 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10891 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10892 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10893 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10894 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10895 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10896 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10897 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10898 rsurface.colormod[3] = ent->alpha;
10899 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10900 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10901 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10902 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10903 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10904 if (ent->model->brush.submodel && !prepass)
10906 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10907 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10909 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10911 if (ent->animcache_vertex3f && !r_framedata_failed)
10913 rsurface.modelvertex3f = ent->animcache_vertex3f;
10914 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10915 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10916 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10917 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
10918 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
10919 rsurface.modelvertexposition = ent->animcache_vertexposition;
10920 rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
10922 else if (wanttangents)
10924 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10925 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10926 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10927 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10928 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
10929 rsurface.modelvertexmesh = NULL;
10930 rsurface.modelvertexmeshbuffer = NULL;
10931 rsurface.modelvertexposition = NULL;
10932 rsurface.modelvertexpositionbuffer = NULL;
10934 else if (wantnormals)
10936 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10937 rsurface.modelsvector3f = NULL;
10938 rsurface.modeltvector3f = NULL;
10939 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10940 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
10941 rsurface.modelvertexmesh = NULL;
10942 rsurface.modelvertexmeshbuffer = NULL;
10943 rsurface.modelvertexposition = NULL;
10944 rsurface.modelvertexpositionbuffer = NULL;
10948 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10949 rsurface.modelsvector3f = NULL;
10950 rsurface.modeltvector3f = NULL;
10951 rsurface.modelnormal3f = NULL;
10952 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
10953 rsurface.modelvertexmesh = NULL;
10954 rsurface.modelvertexmeshbuffer = NULL;
10955 rsurface.modelvertexposition = NULL;
10956 rsurface.modelvertexpositionbuffer = NULL;
10958 rsurface.modelvertex3f_vertexbuffer = 0;
10959 rsurface.modelvertex3f_bufferoffset = 0;
10960 rsurface.modelsvector3f_vertexbuffer = 0;
10961 rsurface.modelsvector3f_bufferoffset = 0;
10962 rsurface.modeltvector3f_vertexbuffer = 0;
10963 rsurface.modeltvector3f_bufferoffset = 0;
10964 rsurface.modelnormal3f_vertexbuffer = 0;
10965 rsurface.modelnormal3f_bufferoffset = 0;
10966 rsurface.modelgeneratedvertex = true;
10970 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
10971 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10972 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10973 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10974 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10975 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10976 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10977 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10978 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10979 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
10980 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10981 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10982 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10983 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10984 rsurface.modelvertexposition = model->surfmesh.vertexposition;
10985 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10986 rsurface.modelgeneratedvertex = false;
10988 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
10989 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10990 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10991 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
10992 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10993 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10994 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
10995 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10996 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10997 rsurface.modelelement3i = model->surfmesh.data_element3i;
10998 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10999 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11000 rsurface.modelelement3s = model->surfmesh.data_element3s;
11001 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11002 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11003 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11004 rsurface.modelnumvertices = model->surfmesh.num_vertices;
11005 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11006 rsurface.modelsurfaces = model->data_surfaces;
11007 rsurface.batchgeneratedvertex = false;
11008 rsurface.batchfirstvertex = 0;
11009 rsurface.batchnumvertices = 0;
11010 rsurface.batchfirsttriangle = 0;
11011 rsurface.batchnumtriangles = 0;
11012 rsurface.batchvertex3f = NULL;
11013 rsurface.batchvertex3f_vertexbuffer = NULL;
11014 rsurface.batchvertex3f_bufferoffset = 0;
11015 rsurface.batchsvector3f = NULL;
11016 rsurface.batchsvector3f_vertexbuffer = NULL;
11017 rsurface.batchsvector3f_bufferoffset = 0;
11018 rsurface.batchtvector3f = NULL;
11019 rsurface.batchtvector3f_vertexbuffer = NULL;
11020 rsurface.batchtvector3f_bufferoffset = 0;
11021 rsurface.batchnormal3f = NULL;
11022 rsurface.batchnormal3f_vertexbuffer = NULL;
11023 rsurface.batchnormal3f_bufferoffset = 0;
11024 rsurface.batchlightmapcolor4f = NULL;
11025 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11026 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11027 rsurface.batchtexcoordtexture2f = NULL;
11028 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11029 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11030 rsurface.batchtexcoordlightmap2f = NULL;
11031 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11032 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11033 rsurface.batchvertexmesh = NULL;
11034 rsurface.batchvertexmeshbuffer = NULL;
11035 rsurface.batchvertexposition = NULL;
11036 rsurface.batchvertexpositionbuffer = NULL;
11037 rsurface.batchelement3i = NULL;
11038 rsurface.batchelement3i_indexbuffer = NULL;
11039 rsurface.batchelement3i_bufferoffset = 0;
11040 rsurface.batchelement3s = NULL;
11041 rsurface.batchelement3s_indexbuffer = NULL;
11042 rsurface.batchelement3s_bufferoffset = 0;
11043 rsurface.passcolor4f = NULL;
11044 rsurface.passcolor4f_vertexbuffer = NULL;
11045 rsurface.passcolor4f_bufferoffset = 0;
11048 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)
11052 rsurface.entity = r_refdef.scene.worldentity;
11053 rsurface.skeleton = NULL;
11054 rsurface.ent_skinnum = 0;
11055 rsurface.ent_qwskin = -1;
11056 rsurface.ent_shadertime = shadertime;
11057 rsurface.ent_flags = entflags;
11058 rsurface.modelnumvertices = numvertices;
11059 rsurface.modelnumtriangles = numtriangles;
11060 if (rsurface.array_size < rsurface.modelnumvertices)
11061 R_Mesh_ResizeArrays(rsurface.modelnumvertices);
11062 rsurface.matrix = *matrix;
11063 rsurface.inversematrix = *inversematrix;
11064 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11065 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11066 R_EntityMatrix(&rsurface.matrix);
11067 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11068 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11069 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11070 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11071 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11072 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11073 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11074 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11075 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11076 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11077 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11078 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
11079 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);
11080 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11081 rsurface.frameblend[0].lerp = 1;
11082 rsurface.ent_alttextures = false;
11083 rsurface.basepolygonfactor = r_refdef.polygonfactor;
11084 rsurface.basepolygonoffset = r_refdef.polygonoffset;
11087 rsurface.modelvertex3f = vertex3f;
11088 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
11089 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
11090 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11092 else if (wantnormals)
11094 rsurface.modelvertex3f = vertex3f;
11095 rsurface.modelsvector3f = NULL;
11096 rsurface.modeltvector3f = NULL;
11097 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11101 rsurface.modelvertex3f = vertex3f;
11102 rsurface.modelsvector3f = NULL;
11103 rsurface.modeltvector3f = NULL;
11104 rsurface.modelnormal3f = NULL;
11106 rsurface.modelvertexmesh = NULL;
11107 rsurface.modelvertexmeshbuffer = NULL;
11108 rsurface.modelvertexposition = NULL;
11109 rsurface.modelvertexpositionbuffer = NULL;
11110 rsurface.modelvertex3f_vertexbuffer = 0;
11111 rsurface.modelvertex3f_bufferoffset = 0;
11112 rsurface.modelsvector3f_vertexbuffer = 0;
11113 rsurface.modelsvector3f_bufferoffset = 0;
11114 rsurface.modeltvector3f_vertexbuffer = 0;
11115 rsurface.modeltvector3f_bufferoffset = 0;
11116 rsurface.modelnormal3f_vertexbuffer = 0;
11117 rsurface.modelnormal3f_bufferoffset = 0;
11118 rsurface.modelgeneratedvertex = true;
11119 rsurface.modellightmapcolor4f = color4f;
11120 rsurface.modellightmapcolor4f_vertexbuffer = 0;
11121 rsurface.modellightmapcolor4f_bufferoffset = 0;
11122 rsurface.modeltexcoordtexture2f = texcoord2f;
11123 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
11124 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
11125 rsurface.modeltexcoordlightmap2f = NULL;
11126 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
11127 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
11128 rsurface.modelelement3i = element3i;
11129 rsurface.modelelement3i_indexbuffer = NULL;
11130 rsurface.modelelement3i_bufferoffset = 0;
11131 rsurface.modelelement3s = element3s;
11132 rsurface.modelelement3s_indexbuffer = NULL;
11133 rsurface.modelelement3s_bufferoffset = 0;
11134 rsurface.modellightmapoffsets = NULL;
11135 rsurface.modelsurfaces = NULL;
11136 rsurface.batchgeneratedvertex = false;
11137 rsurface.batchfirstvertex = 0;
11138 rsurface.batchnumvertices = 0;
11139 rsurface.batchfirsttriangle = 0;
11140 rsurface.batchnumtriangles = 0;
11141 rsurface.batchvertex3f = NULL;
11142 rsurface.batchvertex3f_vertexbuffer = NULL;
11143 rsurface.batchvertex3f_bufferoffset = 0;
11144 rsurface.batchsvector3f = NULL;
11145 rsurface.batchsvector3f_vertexbuffer = NULL;
11146 rsurface.batchsvector3f_bufferoffset = 0;
11147 rsurface.batchtvector3f = NULL;
11148 rsurface.batchtvector3f_vertexbuffer = NULL;
11149 rsurface.batchtvector3f_bufferoffset = 0;
11150 rsurface.batchnormal3f = NULL;
11151 rsurface.batchnormal3f_vertexbuffer = NULL;
11152 rsurface.batchnormal3f_bufferoffset = 0;
11153 rsurface.batchlightmapcolor4f = NULL;
11154 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11155 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11156 rsurface.batchtexcoordtexture2f = NULL;
11157 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11158 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11159 rsurface.batchtexcoordlightmap2f = NULL;
11160 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11161 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11162 rsurface.batchvertexmesh = NULL;
11163 rsurface.batchvertexmeshbuffer = NULL;
11164 rsurface.batchvertexposition = NULL;
11165 rsurface.batchvertexpositionbuffer = NULL;
11166 rsurface.batchelement3i = NULL;
11167 rsurface.batchelement3i_indexbuffer = NULL;
11168 rsurface.batchelement3i_bufferoffset = 0;
11169 rsurface.batchelement3s = NULL;
11170 rsurface.batchelement3s_indexbuffer = NULL;
11171 rsurface.batchelement3s_bufferoffset = 0;
11172 rsurface.passcolor4f = NULL;
11173 rsurface.passcolor4f_vertexbuffer = NULL;
11174 rsurface.passcolor4f_bufferoffset = 0;
11176 if (rsurface.modelnumvertices && rsurface.modelelement3i)
11178 if ((wantnormals || wanttangents) && !normal3f)
11180 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
11181 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11183 if (wanttangents && !svector3f)
11185 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
11186 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11187 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11191 // now convert arrays into vertexmesh structs
11192 for (i = 0;i < numvertices;i++)
11194 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexposition[i].vertex3f);
11195 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexmesh[i].vertex3f);
11196 if (rsurface.modelsvector3f)
11197 VectorCopy(rsurface.modelsvector3f + 3*i, rsurface.array_modelvertexmesh[i].svector3f);
11198 if (rsurface.modeltvector3f)
11199 VectorCopy(rsurface.modeltvector3f + 3*i, rsurface.array_modelvertexmesh[i].tvector3f);
11200 if (rsurface.modelnormal3f)
11201 VectorCopy(rsurface.modelnormal3f + 3*i, rsurface.array_modelvertexmesh[i].normal3f);
11202 if (rsurface.modellightmapcolor4f)
11203 Vector4Scale(rsurface.modellightmapcolor4f + 4*i, 255.0f, rsurface.array_modelvertexmesh[i].color4ub);
11204 if (rsurface.modeltexcoordtexture2f)
11205 Vector2Copy(rsurface.modeltexcoordtexture2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordtexture2f);
11206 if (rsurface.modeltexcoordlightmap2f)
11207 Vector2Copy(rsurface.modeltexcoordlightmap2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordlightmap2f);
11211 float RSurf_FogPoint(const float *v)
11213 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11214 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11215 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11216 float FogHeightFade = r_refdef.fogheightfade;
11218 unsigned int fogmasktableindex;
11219 if (r_refdef.fogplaneviewabove)
11220 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11222 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11223 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11224 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11227 float RSurf_FogVertex(const float *v)
11229 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11230 float FogPlaneViewDist = rsurface.fogplaneviewdist;
11231 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11232 float FogHeightFade = rsurface.fogheightfade;
11234 unsigned int fogmasktableindex;
11235 if (r_refdef.fogplaneviewabove)
11236 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11238 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11239 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11240 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11243 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11246 for (i = 0;i < numelements;i++)
11247 outelement3i[i] = inelement3i[i] + adjust;
11250 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11251 extern cvar_t gl_vbo;
11252 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11260 int surfacefirsttriangle;
11261 int surfacenumtriangles;
11262 int surfacefirstvertex;
11263 int surfaceendvertex;
11264 int surfacenumvertices;
11268 qboolean dynamicvertex;
11272 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11273 float waveparms[4];
11274 q3shaderinfo_deform_t *deform;
11275 const msurface_t *surface, *firstsurface;
11276 r_vertexposition_t *vertexposition;
11277 r_vertexmesh_t *vertexmesh;
11278 if (!texturenumsurfaces)
11280 // find vertex range of this surface batch
11282 firstsurface = texturesurfacelist[0];
11283 firsttriangle = firstsurface->num_firsttriangle;
11285 firstvertex = endvertex = firstsurface->num_firstvertex;
11286 for (i = 0;i < texturenumsurfaces;i++)
11288 surface = texturesurfacelist[i];
11289 if (surface != firstsurface + i)
11291 surfacefirstvertex = surface->num_firstvertex;
11292 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11293 surfacenumtriangles = surface->num_triangles;
11294 if (firstvertex > surfacefirstvertex)
11295 firstvertex = surfacefirstvertex;
11296 if (endvertex < surfaceendvertex)
11297 endvertex = surfaceendvertex;
11298 numtriangles += surfacenumtriangles;
11303 // we now know the vertex range used, and if there are any gaps in it
11304 rsurface.batchfirstvertex = firstvertex;
11305 rsurface.batchnumvertices = endvertex - firstvertex;
11306 rsurface.batchfirsttriangle = firsttriangle;
11307 rsurface.batchnumtriangles = numtriangles;
11309 // this variable holds flags for which properties have been updated that
11310 // may require regenerating vertexmesh or vertexposition arrays...
11313 // check if any dynamic vertex processing must occur
11314 dynamicvertex = false;
11316 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11317 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
11318 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11320 switch (deform->deform)
11323 case Q3DEFORM_PROJECTIONSHADOW:
11324 case Q3DEFORM_TEXT0:
11325 case Q3DEFORM_TEXT1:
11326 case Q3DEFORM_TEXT2:
11327 case Q3DEFORM_TEXT3:
11328 case Q3DEFORM_TEXT4:
11329 case Q3DEFORM_TEXT5:
11330 case Q3DEFORM_TEXT6:
11331 case Q3DEFORM_TEXT7:
11332 case Q3DEFORM_NONE:
11334 case Q3DEFORM_AUTOSPRITE:
11335 dynamicvertex = true;
11336 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11337 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11339 case Q3DEFORM_AUTOSPRITE2:
11340 dynamicvertex = true;
11341 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11342 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11344 case Q3DEFORM_NORMAL:
11345 dynamicvertex = true;
11346 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11347 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11349 case Q3DEFORM_WAVE:
11350 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11351 break; // if wavefunc is a nop, ignore this transform
11352 dynamicvertex = true;
11353 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11354 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11356 case Q3DEFORM_BULGE:
11357 dynamicvertex = true;
11358 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11359 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11361 case Q3DEFORM_MOVE:
11362 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11363 break; // if wavefunc is a nop, ignore this transform
11364 dynamicvertex = true;
11365 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11366 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
11370 switch(rsurface.texture->tcgen.tcgen)
11373 case Q3TCGEN_TEXTURE:
11375 case Q3TCGEN_LIGHTMAP:
11376 dynamicvertex = true;
11377 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11378 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11380 case Q3TCGEN_VECTOR:
11381 dynamicvertex = true;
11382 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11383 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11385 case Q3TCGEN_ENVIRONMENT:
11386 dynamicvertex = true;
11387 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11388 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11391 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11393 dynamicvertex = true;
11394 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11395 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11398 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11400 dynamicvertex = true;
11401 batchneed |= BATCHNEED_NOGAPS;
11402 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11405 if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11407 dynamicvertex = true;
11408 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11409 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
11412 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11414 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11415 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
11416 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
11417 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
11418 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11419 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11420 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11423 // when the model data has no vertex buffer (dynamic mesh), we need to
11425 if (!rsurface.modelvertexmeshbuffer)
11426 batchneed |= BATCHNEED_NOGAPS;
11428 // if needsupdate, we have to do a dynamic vertex batch for sure
11429 if (needsupdate & batchneed)
11430 dynamicvertex = true;
11432 // see if we need to build vertexmesh from arrays
11433 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11434 dynamicvertex = true;
11436 // see if we need to build vertexposition from arrays
11437 if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
11438 dynamicvertex = true;
11440 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11441 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11442 dynamicvertex = true;
11444 // if there is a chance of animated vertex colors, it's a dynamic batch
11445 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11446 dynamicvertex = true;
11448 rsurface.batchvertex3f = rsurface.modelvertex3f;
11449 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11450 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11451 rsurface.batchsvector3f = rsurface.modelsvector3f;
11452 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11453 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11454 rsurface.batchtvector3f = rsurface.modeltvector3f;
11455 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11456 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11457 rsurface.batchnormal3f = rsurface.modelnormal3f;
11458 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11459 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11460 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11461 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
11462 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11463 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11464 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
11465 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
11466 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11467 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11468 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11469 rsurface.batchvertexposition = rsurface.modelvertexposition;
11470 rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
11471 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11472 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11473 rsurface.batchelement3i = rsurface.modelelement3i;
11474 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11475 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11476 rsurface.batchelement3s = rsurface.modelelement3s;
11477 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11478 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11480 // if any dynamic vertex processing has to occur in software, we copy the
11481 // entire surface list together before processing to rebase the vertices
11482 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11484 // if any gaps exist and we do not have a static vertex buffer, we have to
11485 // copy the surface list together to avoid wasting upload bandwidth on the
11486 // vertices in the gaps.
11488 // if gaps exist and we have a static vertex buffer, we still have to
11489 // combine the index buffer ranges into one dynamic index buffer.
11491 // in all cases we end up with data that can be drawn in one call.
11493 if (!dynamicvertex)
11495 // static vertex data, just set pointers...
11496 rsurface.batchgeneratedvertex = false;
11497 // if there are gaps, we want to build a combined index buffer,
11498 // otherwise use the original static buffer with an appropriate offset
11503 for (i = 0;i < texturenumsurfaces;i++)
11505 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11506 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11507 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11508 numtriangles += surfacenumtriangles;
11510 rsurface.batchelement3i = rsurface.array_batchelement3i;
11511 rsurface.batchelement3i_indexbuffer = NULL;
11512 rsurface.batchelement3i_bufferoffset = 0;
11513 rsurface.batchelement3s = NULL;
11514 rsurface.batchelement3s_indexbuffer = NULL;
11515 rsurface.batchelement3s_bufferoffset = 0;
11516 if (endvertex <= 65536)
11518 rsurface.batchelement3s = rsurface.array_batchelement3s;
11519 for (i = 0;i < numtriangles*3;i++)
11520 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11522 rsurface.batchfirsttriangle = firsttriangle;
11523 rsurface.batchnumtriangles = numtriangles;
11528 // something needs software processing, do it for real...
11529 // we only directly handle interleaved array data in this case...
11530 rsurface.batchgeneratedvertex = true;
11532 // now copy the vertex data into a combined array and make an index array
11533 // (this is what Quake3 does all the time)
11534 //if (gaps || rsurface.batchfirstvertex)
11536 rsurface.batchvertexposition = NULL;
11537 rsurface.batchvertexpositionbuffer = NULL;
11538 rsurface.batchvertexmesh = NULL;
11539 rsurface.batchvertexmeshbuffer = NULL;
11540 rsurface.batchvertex3f = NULL;
11541 rsurface.batchvertex3f_vertexbuffer = NULL;
11542 rsurface.batchvertex3f_bufferoffset = 0;
11543 rsurface.batchsvector3f = NULL;
11544 rsurface.batchsvector3f_vertexbuffer = NULL;
11545 rsurface.batchsvector3f_bufferoffset = 0;
11546 rsurface.batchtvector3f = NULL;
11547 rsurface.batchtvector3f_vertexbuffer = NULL;
11548 rsurface.batchtvector3f_bufferoffset = 0;
11549 rsurface.batchnormal3f = NULL;
11550 rsurface.batchnormal3f_vertexbuffer = NULL;
11551 rsurface.batchnormal3f_bufferoffset = 0;
11552 rsurface.batchlightmapcolor4f = NULL;
11553 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11554 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11555 rsurface.batchtexcoordtexture2f = NULL;
11556 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11557 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11558 rsurface.batchtexcoordlightmap2f = NULL;
11559 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11560 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11561 rsurface.batchelement3i = rsurface.array_batchelement3i;
11562 rsurface.batchelement3i_indexbuffer = NULL;
11563 rsurface.batchelement3i_bufferoffset = 0;
11564 rsurface.batchelement3s = NULL;
11565 rsurface.batchelement3s_indexbuffer = NULL;
11566 rsurface.batchelement3s_bufferoffset = 0;
11567 // we'll only be setting up certain arrays as needed
11568 if (batchneed & BATCHNEED_VERTEXPOSITION)
11569 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11570 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11571 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11572 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11573 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11574 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11575 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11576 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11578 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11579 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11581 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11582 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11583 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11584 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11585 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11586 rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
11589 for (i = 0;i < texturenumsurfaces;i++)
11591 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11592 surfacenumvertices = texturesurfacelist[i]->num_vertices;
11593 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11594 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11595 // copy only the data requested
11596 if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
11597 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
11598 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11599 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11600 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11602 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11603 memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11604 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11605 memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11606 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11608 memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11609 memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11611 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11612 memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11613 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11614 memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11615 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11616 memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11618 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11619 numvertices += surfacenumvertices;
11620 numtriangles += surfacenumtriangles;
11623 // generate a 16bit index array as well if possible
11624 // (in general, dynamic batches fit)
11625 if (numvertices <= 65536)
11627 rsurface.batchelement3s = rsurface.array_batchelement3s;
11628 for (i = 0;i < numtriangles*3;i++)
11629 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11632 // since we've copied everything, the batch now starts at 0
11633 rsurface.batchfirstvertex = 0;
11634 rsurface.batchnumvertices = numvertices;
11635 rsurface.batchfirsttriangle = 0;
11636 rsurface.batchnumtriangles = numtriangles;
11639 // q1bsp surfaces rendered in vertex color mode have to have colors
11640 // calculated based on lightstyles
11641 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11643 // generate color arrays for the surfaces in this list
11647 const int *offsets;
11648 const unsigned char *lm;
11650 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11651 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11652 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11653 for (i = 0;i < texturenumsurfaces;i++)
11655 surface = texturesurfacelist[i];
11656 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11657 surfacenumvertices = surface->num_vertices;
11658 if (surface->lightmapinfo->samples)
11660 for (j = 0;j < surfacenumvertices;j++)
11662 lm = surface->lightmapinfo->samples + offsets[j];
11663 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11664 VectorScale(lm, scale, c);
11665 if (surface->lightmapinfo->styles[1] != 255)
11667 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11669 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11670 VectorMA(c, scale, lm, c);
11671 if (surface->lightmapinfo->styles[2] != 255)
11674 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11675 VectorMA(c, scale, lm, c);
11676 if (surface->lightmapinfo->styles[3] != 255)
11679 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11680 VectorMA(c, scale, lm, c);
11687 Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, min(c[0], 255) * (1.0f / 255.0f), min(c[1], 255) * (1.0f / 255.0f), min(c[2], 255) * (1.0f / 255.0f), 1);
11693 for (j = 0;j < surfacenumvertices;j++)
11695 Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11702 // if vertices are deformed (sprite flares and things in maps, possibly
11703 // water waves, bulges and other deformations), modify the copied vertices
11705 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11707 switch (deform->deform)
11710 case Q3DEFORM_PROJECTIONSHADOW:
11711 case Q3DEFORM_TEXT0:
11712 case Q3DEFORM_TEXT1:
11713 case Q3DEFORM_TEXT2:
11714 case Q3DEFORM_TEXT3:
11715 case Q3DEFORM_TEXT4:
11716 case Q3DEFORM_TEXT5:
11717 case Q3DEFORM_TEXT6:
11718 case Q3DEFORM_TEXT7:
11719 case Q3DEFORM_NONE:
11721 case Q3DEFORM_AUTOSPRITE:
11722 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11723 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11724 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11725 VectorNormalize(newforward);
11726 VectorNormalize(newright);
11727 VectorNormalize(newup);
11728 // a single autosprite surface can contain multiple sprites...
11729 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11731 VectorClear(center);
11732 for (i = 0;i < 4;i++)
11733 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11734 VectorScale(center, 0.25f, center);
11735 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11736 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11737 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11738 for (i = 0;i < 4;i++)
11740 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11741 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
11744 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11745 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11746 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
11747 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11748 rsurface.batchvertex3f_vertexbuffer = NULL;
11749 rsurface.batchvertex3f_bufferoffset = 0;
11750 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11751 rsurface.batchsvector3f_vertexbuffer = NULL;
11752 rsurface.batchsvector3f_bufferoffset = 0;
11753 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11754 rsurface.batchtvector3f_vertexbuffer = NULL;
11755 rsurface.batchtvector3f_bufferoffset = 0;
11756 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11757 rsurface.batchnormal3f_vertexbuffer = NULL;
11758 rsurface.batchnormal3f_bufferoffset = 0;
11760 case Q3DEFORM_AUTOSPRITE2:
11761 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11762 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11763 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11764 VectorNormalize(newforward);
11765 VectorNormalize(newright);
11766 VectorNormalize(newup);
11768 const float *v1, *v2;
11778 memset(shortest, 0, sizeof(shortest));
11779 // a single autosprite surface can contain multiple sprites...
11780 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11782 VectorClear(center);
11783 for (i = 0;i < 4;i++)
11784 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11785 VectorScale(center, 0.25f, center);
11786 // find the two shortest edges, then use them to define the
11787 // axis vectors for rotating around the central axis
11788 for (i = 0;i < 6;i++)
11790 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11791 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11792 l = VectorDistance2(v1, v2);
11793 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11794 if (v1[2] != v2[2])
11795 l += (1.0f / 1024.0f);
11796 if (shortest[0].length2 > l || i == 0)
11798 shortest[1] = shortest[0];
11799 shortest[0].length2 = l;
11800 shortest[0].v1 = v1;
11801 shortest[0].v2 = v2;
11803 else if (shortest[1].length2 > l || i == 1)
11805 shortest[1].length2 = l;
11806 shortest[1].v1 = v1;
11807 shortest[1].v2 = v2;
11810 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11811 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11812 // this calculates the right vector from the shortest edge
11813 // and the up vector from the edge midpoints
11814 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11815 VectorNormalize(right);
11816 VectorSubtract(end, start, up);
11817 VectorNormalize(up);
11818 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11819 VectorSubtract(rsurface.localvieworigin, center, forward);
11820 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11821 VectorNegate(forward, forward);
11822 VectorReflect(forward, 0, up, forward);
11823 VectorNormalize(forward);
11824 CrossProduct(up, forward, newright);
11825 VectorNormalize(newright);
11826 // rotate the quad around the up axis vector, this is made
11827 // especially easy by the fact we know the quad is flat,
11828 // so we only have to subtract the center position and
11829 // measure distance along the right vector, and then
11830 // multiply that by the newright vector and add back the
11832 // we also need to subtract the old position to undo the
11833 // displacement from the center, which we do with a
11834 // DotProduct, the subtraction/addition of center is also
11835 // optimized into DotProducts here
11836 l = DotProduct(right, center);
11837 for (i = 0;i < 4;i++)
11839 v1 = rsurface.batchvertex3f + 3*(j+i);
11840 f = DotProduct(right, v1) - l;
11841 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
11845 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11846 rsurface.batchvertex3f_vertexbuffer = NULL;
11847 rsurface.batchvertex3f_bufferoffset = 0;
11848 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11850 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11851 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11852 rsurface.batchnormal3f_vertexbuffer = NULL;
11853 rsurface.batchnormal3f_bufferoffset = 0;
11855 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11857 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
11858 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11859 rsurface.batchsvector3f_vertexbuffer = NULL;
11860 rsurface.batchsvector3f_bufferoffset = 0;
11861 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11862 rsurface.batchtvector3f_vertexbuffer = NULL;
11863 rsurface.batchtvector3f_bufferoffset = 0;
11866 case Q3DEFORM_NORMAL:
11867 // deform the normals to make reflections wavey
11868 for (j = 0;j < rsurface.batchnumvertices;j++)
11871 float *normal = rsurface.array_batchnormal3f + 3*j;
11872 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11873 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11874 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11875 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11876 VectorNormalize(normal);
11878 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11879 rsurface.batchnormal3f_vertexbuffer = NULL;
11880 rsurface.batchnormal3f_bufferoffset = 0;
11881 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11883 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
11884 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11885 rsurface.batchsvector3f_vertexbuffer = NULL;
11886 rsurface.batchsvector3f_bufferoffset = 0;
11887 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11888 rsurface.batchtvector3f_vertexbuffer = NULL;
11889 rsurface.batchtvector3f_bufferoffset = 0;
11892 case Q3DEFORM_WAVE:
11893 // deform vertex array to make wavey water and flags and such
11894 waveparms[0] = deform->waveparms[0];
11895 waveparms[1] = deform->waveparms[1];
11896 waveparms[2] = deform->waveparms[2];
11897 waveparms[3] = deform->waveparms[3];
11898 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11899 break; // if wavefunc is a nop, don't make a dynamic vertex array
11900 // this is how a divisor of vertex influence on deformation
11901 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11902 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11903 for (j = 0;j < rsurface.batchnumvertices;j++)
11905 // if the wavefunc depends on time, evaluate it per-vertex
11908 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11909 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11911 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11913 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11914 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11915 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11916 rsurface.batchvertex3f_vertexbuffer = NULL;
11917 rsurface.batchvertex3f_bufferoffset = 0;
11918 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11919 rsurface.batchnormal3f_vertexbuffer = NULL;
11920 rsurface.batchnormal3f_bufferoffset = 0;
11921 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11923 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
11924 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11925 rsurface.batchsvector3f_vertexbuffer = NULL;
11926 rsurface.batchsvector3f_bufferoffset = 0;
11927 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11928 rsurface.batchtvector3f_vertexbuffer = NULL;
11929 rsurface.batchtvector3f_bufferoffset = 0;
11932 case Q3DEFORM_BULGE:
11933 // deform vertex array to make the surface have moving bulges
11934 for (j = 0;j < rsurface.batchnumvertices;j++)
11936 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
11937 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11939 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11940 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11941 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11942 rsurface.batchvertex3f_vertexbuffer = NULL;
11943 rsurface.batchvertex3f_bufferoffset = 0;
11944 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11945 rsurface.batchnormal3f_vertexbuffer = NULL;
11946 rsurface.batchnormal3f_bufferoffset = 0;
11947 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11949 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
11950 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11951 rsurface.batchsvector3f_vertexbuffer = NULL;
11952 rsurface.batchsvector3f_bufferoffset = 0;
11953 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11954 rsurface.batchtvector3f_vertexbuffer = NULL;
11955 rsurface.batchtvector3f_bufferoffset = 0;
11958 case Q3DEFORM_MOVE:
11959 // deform vertex array
11960 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11961 break; // if wavefunc is a nop, don't make a dynamic vertex array
11962 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
11963 VectorScale(deform->parms, scale, waveparms);
11964 for (j = 0;j < rsurface.batchnumvertices;j++)
11965 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
11966 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11967 rsurface.batchvertex3f_vertexbuffer = NULL;
11968 rsurface.batchvertex3f_bufferoffset = 0;
11973 // generate texcoords based on the chosen texcoord source
11974 switch(rsurface.texture->tcgen.tcgen)
11977 case Q3TCGEN_TEXTURE:
11979 case Q3TCGEN_LIGHTMAP:
11980 if (rsurface.batchtexcoordlightmap2f)
11981 memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
11982 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11983 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11984 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11986 case Q3TCGEN_VECTOR:
11987 for (j = 0;j < rsurface.batchnumvertices;j++)
11989 rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
11990 rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
11992 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11993 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11994 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11996 case Q3TCGEN_ENVIRONMENT:
11997 // make environment reflections using a spheremap
11998 for (j = 0;j < rsurface.batchnumvertices;j++)
12000 // identical to Q3A's method, but executed in worldspace so
12001 // carried models can be shiny too
12003 float viewer[3], d, reflected[3], worldreflected[3];
12005 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
12006 // VectorNormalize(viewer);
12008 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
12010 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
12011 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
12012 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
12013 // note: this is proportinal to viewer, so we can normalize later
12015 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
12016 VectorNormalize(worldreflected);
12018 // note: this sphere map only uses world x and z!
12019 // so positive and negative y will LOOK THE SAME.
12020 rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
12021 rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
12023 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12024 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12025 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12028 // the only tcmod that needs software vertex processing is turbulent, so
12029 // check for it here and apply the changes if needed
12030 // and we only support that as the first one
12031 // (handling a mixture of turbulent and other tcmods would be problematic
12032 // without punting it entirely to a software path)
12033 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
12035 amplitude = rsurface.texture->tcmods[0].parms[1];
12036 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
12037 for (j = 0;j < rsurface.batchnumvertices;j++)
12039 rsurface.array_batchtexcoordtexture2f[j*2+0] += amplitude * sin(((rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12040 rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12042 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12043 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12044 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12047 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
12049 // convert the modified arrays to vertex structs
12050 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
12051 rsurface.batchvertexmeshbuffer = NULL;
12052 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
12053 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12054 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
12055 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
12056 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12057 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
12058 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
12060 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12062 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
12063 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
12066 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
12067 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12068 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
12069 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
12070 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12071 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
12072 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
12073 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12074 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
12077 if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
12079 // convert the modified arrays to vertex structs
12080 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
12081 rsurface.batchvertexpositionbuffer = NULL;
12082 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
12083 memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
12085 for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
12086 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
12090 void RSurf_DrawBatch(void)
12092 R_Mesh_Draw(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchfirsttriangle, rsurface.batchnumtriangles, rsurface.batchelement3i, rsurface.batchelement3i_indexbuffer, rsurface.batchelement3i_bufferoffset, rsurface.batchelement3s, rsurface.batchelement3s_indexbuffer, rsurface.batchelement3s_bufferoffset);
12095 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
12097 // pick the closest matching water plane
12098 int planeindex, vertexindex, bestplaneindex = -1;
12102 r_waterstate_waterplane_t *p;
12104 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
12106 if(p->camera_entity != rsurface.texture->camera_entity)
12109 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
12110 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
12112 Matrix4x4_Transform(&rsurface.matrix, v, vert);
12113 d += fabs(PlaneDiff(vert, &p->plane));
12115 if (bestd > d || bestplaneindex < 0)
12118 bestplaneindex = planeindex;
12121 return bestplaneindex;
12124 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
12127 for (i = 0;i < rsurface.batchnumvertices;i++)
12128 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
12129 rsurface.passcolor4f = rsurface.array_passcolor4f;
12130 rsurface.passcolor4f_vertexbuffer = 0;
12131 rsurface.passcolor4f_bufferoffset = 0;
12134 static void RSurf_DrawBatch_GL11_ApplyFog(void)
12141 if (rsurface.passcolor4f)
12143 // generate color arrays
12144 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
12146 f = RSurf_FogVertex(v);
12155 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
12157 f = RSurf_FogVertex(v);
12164 rsurface.passcolor4f = rsurface.array_passcolor4f;
12165 rsurface.passcolor4f_vertexbuffer = 0;
12166 rsurface.passcolor4f_bufferoffset = 0;
12169 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
12176 if (!rsurface.passcolor4f)
12178 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
12180 f = RSurf_FogVertex(v);
12181 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
12182 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
12183 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
12186 rsurface.passcolor4f = rsurface.array_passcolor4f;
12187 rsurface.passcolor4f_vertexbuffer = 0;
12188 rsurface.passcolor4f_bufferoffset = 0;
12191 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
12196 if (!rsurface.passcolor4f)
12198 for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12205 rsurface.passcolor4f = rsurface.array_passcolor4f;
12206 rsurface.passcolor4f_vertexbuffer = 0;
12207 rsurface.passcolor4f_bufferoffset = 0;
12210 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12215 if (!rsurface.passcolor4f)
12217 for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12219 c2[0] = c[0] + r_refdef.scene.ambient;
12220 c2[1] = c[1] + r_refdef.scene.ambient;
12221 c2[2] = c[2] + r_refdef.scene.ambient;
12224 rsurface.passcolor4f = rsurface.array_passcolor4f;
12225 rsurface.passcolor4f_vertexbuffer = 0;
12226 rsurface.passcolor4f_bufferoffset = 0;
12229 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12232 rsurface.passcolor4f = NULL;
12233 rsurface.passcolor4f_vertexbuffer = 0;
12234 rsurface.passcolor4f_bufferoffset = 0;
12235 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12236 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12237 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12238 GL_Color(r, g, b, a);
12239 R_Mesh_TexBind(0, rsurface.lightmaptexture);
12243 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12245 // TODO: optimize applyfog && applycolor case
12246 // just apply fog if necessary, and tint the fog color array if necessary
12247 rsurface.passcolor4f = NULL;
12248 rsurface.passcolor4f_vertexbuffer = 0;
12249 rsurface.passcolor4f_bufferoffset = 0;
12250 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12251 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12252 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12253 GL_Color(r, g, b, a);
12257 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12260 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12261 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12262 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12263 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12264 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12265 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12266 GL_Color(r, g, b, a);
12270 static void RSurf_DrawBatch_GL11_ClampColor(void)
12275 if (!rsurface.passcolor4f)
12277 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12279 c2[0] = bound(0.0f, c1[0], 1.0f);
12280 c2[1] = bound(0.0f, c1[1], 1.0f);
12281 c2[2] = bound(0.0f, c1[2], 1.0f);
12282 c2[3] = bound(0.0f, c1[3], 1.0f);
12286 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
12296 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
12298 f = -DotProduct(r_refdef.view.forward, n);
12300 f = f * 0.85 + 0.15; // work around so stuff won't get black
12301 f *= r_refdef.lightmapintensity;
12302 Vector4Set(c, f, f, f, 1);
12305 rsurface.passcolor4f = rsurface.array_passcolor4f;
12306 rsurface.passcolor4f_vertexbuffer = 0;
12307 rsurface.passcolor4f_bufferoffset = 0;
12310 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12312 RSurf_DrawBatch_GL11_ApplyFakeLight();
12313 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12314 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12315 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12316 GL_Color(r, g, b, a);
12320 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12328 vec3_t ambientcolor;
12329 vec3_t diffusecolor;
12333 VectorCopy(rsurface.modellight_lightdir, lightdir);
12334 f = 0.5f * r_refdef.lightmapintensity;
12335 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12336 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12337 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12338 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12339 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12340 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12342 if (VectorLength2(diffusecolor) > 0)
12344 // q3-style directional shading
12345 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
12347 if ((f = DotProduct(n, lightdir)) > 0)
12348 VectorMA(ambientcolor, f, diffusecolor, c);
12350 VectorCopy(ambientcolor, c);
12357 rsurface.passcolor4f = rsurface.array_passcolor4f;
12358 rsurface.passcolor4f_vertexbuffer = 0;
12359 rsurface.passcolor4f_bufferoffset = 0;
12360 *applycolor = false;
12364 *r = ambientcolor[0];
12365 *g = ambientcolor[1];
12366 *b = ambientcolor[2];
12367 rsurface.passcolor4f = NULL;
12368 rsurface.passcolor4f_vertexbuffer = 0;
12369 rsurface.passcolor4f_bufferoffset = 0;
12373 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12375 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12376 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12377 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12378 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12379 GL_Color(r, g, b, a);
12383 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12389 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12391 f = 1 - RSurf_FogVertex(v);
12399 void RSurf_SetupDepthAndCulling(void)
12401 // submodels are biased to avoid z-fighting with world surfaces that they
12402 // may be exactly overlapping (avoids z-fighting artifacts on certain
12403 // doors and things in Quake maps)
12404 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12405 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12406 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12407 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12410 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12412 // transparent sky would be ridiculous
12413 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12415 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12416 skyrenderlater = true;
12417 RSurf_SetupDepthAndCulling();
12418 GL_DepthMask(true);
12419 // LordHavoc: HalfLife maps have freaky skypolys so don't use
12420 // skymasking on them, and Quake3 never did sky masking (unlike
12421 // software Quake and software Quake2), so disable the sky masking
12422 // in Quake3 maps as it causes problems with q3map2 sky tricks,
12423 // and skymasking also looks very bad when noclipping outside the
12424 // level, so don't use it then either.
12425 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12427 R_Mesh_ResetTextureState();
12428 if (skyrendermasked)
12430 R_SetupShader_DepthOrShadow();
12431 // depth-only (masking)
12432 GL_ColorMask(0,0,0,0);
12433 // just to make sure that braindead drivers don't draw
12434 // anything despite that colormask...
12435 GL_BlendFunc(GL_ZERO, GL_ONE);
12436 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12437 R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12441 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12443 GL_BlendFunc(GL_ONE, GL_ZERO);
12444 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12445 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12446 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12449 if (skyrendermasked)
12450 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12452 R_Mesh_ResetTextureState();
12453 GL_Color(1, 1, 1, 1);
12456 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12457 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12458 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12460 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12464 // render screenspace normalmap to texture
12465 GL_DepthMask(true);
12466 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12471 // bind lightmap texture
12473 // water/refraction/reflection/camera surfaces have to be handled specially
12474 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)) && !r_waterstate.renderingscene)
12476 int start, end, startplaneindex;
12477 for (start = 0;start < texturenumsurfaces;start = end)
12479 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12480 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12482 // now that we have a batch using the same planeindex, render it
12483 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
12485 // render water or distortion background
12486 GL_DepthMask(true);
12487 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_waterstate.waterplanes + startplaneindex));
12489 // blend surface on top
12490 GL_DepthMask(false);
12491 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12494 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) && !r_waterstate.renderingscene)
12496 // render surface with reflection texture as input
12497 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12498 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_waterstate.waterplanes + startplaneindex));
12505 // render surface batch normally
12506 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12507 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12511 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12513 // OpenGL 1.3 path - anything not completely ancient
12514 qboolean applycolor;
12517 const texturelayer_t *layer;
12518 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12519 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12521 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12524 int layertexrgbscale;
12525 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12527 if (layerindex == 0)
12528 GL_AlphaTest(true);
12531 GL_AlphaTest(false);
12532 GL_DepthFunc(GL_EQUAL);
12535 GL_DepthMask(layer->depthmask && writedepth);
12536 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12537 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12539 layertexrgbscale = 4;
12540 VectorScale(layer->color, 0.25f, layercolor);
12542 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12544 layertexrgbscale = 2;
12545 VectorScale(layer->color, 0.5f, layercolor);
12549 layertexrgbscale = 1;
12550 VectorScale(layer->color, 1.0f, layercolor);
12552 layercolor[3] = layer->color[3];
12553 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12554 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12555 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12556 switch (layer->type)
12558 case TEXTURELAYERTYPE_LITTEXTURE:
12559 // single-pass lightmapped texture with 2x rgbscale
12560 R_Mesh_TexBind(0, r_texture_white);
12561 R_Mesh_TexMatrix(0, NULL);
12562 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12563 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12564 R_Mesh_TexBind(1, layer->texture);
12565 R_Mesh_TexMatrix(1, &layer->texmatrix);
12566 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12567 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12568 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12569 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12570 else if (FAKELIGHT_ENABLED)
12571 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12572 else if (rsurface.uselightmaptexture)
12573 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12575 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12577 case TEXTURELAYERTYPE_TEXTURE:
12578 // singletexture unlit texture with transparency support
12579 R_Mesh_TexBind(0, layer->texture);
12580 R_Mesh_TexMatrix(0, &layer->texmatrix);
12581 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12582 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12583 R_Mesh_TexBind(1, 0);
12584 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12585 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12587 case TEXTURELAYERTYPE_FOG:
12588 // singletexture fogging
12589 if (layer->texture)
12591 R_Mesh_TexBind(0, layer->texture);
12592 R_Mesh_TexMatrix(0, &layer->texmatrix);
12593 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12594 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12598 R_Mesh_TexBind(0, 0);
12599 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12601 R_Mesh_TexBind(1, 0);
12602 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12603 // generate a color array for the fog pass
12604 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12605 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12609 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12612 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12614 GL_DepthFunc(GL_LEQUAL);
12615 GL_AlphaTest(false);
12619 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12621 // OpenGL 1.1 - crusty old voodoo path
12624 const texturelayer_t *layer;
12625 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12626 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12628 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12630 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12632 if (layerindex == 0)
12633 GL_AlphaTest(true);
12636 GL_AlphaTest(false);
12637 GL_DepthFunc(GL_EQUAL);
12640 GL_DepthMask(layer->depthmask && writedepth);
12641 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12642 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12643 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12644 switch (layer->type)
12646 case TEXTURELAYERTYPE_LITTEXTURE:
12647 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12649 // two-pass lit texture with 2x rgbscale
12650 // first the lightmap pass
12651 R_Mesh_TexBind(0, r_texture_white);
12652 R_Mesh_TexMatrix(0, NULL);
12653 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12654 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12655 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12656 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12657 else if (FAKELIGHT_ENABLED)
12658 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12659 else if (rsurface.uselightmaptexture)
12660 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12662 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12663 // then apply the texture to it
12664 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12665 R_Mesh_TexBind(0, layer->texture);
12666 R_Mesh_TexMatrix(0, &layer->texmatrix);
12667 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12668 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12669 RSurf_DrawBatch_GL11_Unlit(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);
12673 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12674 R_Mesh_TexBind(0, layer->texture);
12675 R_Mesh_TexMatrix(0, &layer->texmatrix);
12676 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12677 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12678 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12679 RSurf_DrawBatch_GL11_VertexShade(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);
12681 RSurf_DrawBatch_GL11_VertexColor(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);
12684 case TEXTURELAYERTYPE_TEXTURE:
12685 // singletexture unlit texture with transparency support
12686 R_Mesh_TexBind(0, layer->texture);
12687 R_Mesh_TexMatrix(0, &layer->texmatrix);
12688 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12689 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12690 RSurf_DrawBatch_GL11_Unlit(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);
12692 case TEXTURELAYERTYPE_FOG:
12693 // singletexture fogging
12694 if (layer->texture)
12696 R_Mesh_TexBind(0, layer->texture);
12697 R_Mesh_TexMatrix(0, &layer->texmatrix);
12698 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12699 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12703 R_Mesh_TexBind(0, 0);
12704 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12706 // generate a color array for the fog pass
12707 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12708 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12712 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12715 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12717 GL_DepthFunc(GL_LEQUAL);
12718 GL_AlphaTest(false);
12722 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12726 r_vertexgeneric_t *batchvertex;
12729 GL_AlphaTest(false);
12730 R_Mesh_ResetTextureState();
12731 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12733 if(rsurface.texture && rsurface.texture->currentskinframe)
12735 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12736 c[3] *= rsurface.texture->currentalpha;
12746 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12748 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12749 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12750 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12753 // brighten it up (as texture value 127 means "unlit")
12754 c[0] *= 2 * r_refdef.view.colorscale;
12755 c[1] *= 2 * r_refdef.view.colorscale;
12756 c[2] *= 2 * r_refdef.view.colorscale;
12758 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12759 c[3] *= r_wateralpha.value;
12761 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12763 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12764 GL_DepthMask(false);
12766 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12768 GL_BlendFunc(GL_ONE, GL_ONE);
12769 GL_DepthMask(false);
12771 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12773 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12774 GL_DepthMask(false);
12776 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12778 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12779 GL_DepthMask(false);
12783 GL_BlendFunc(GL_ONE, GL_ZERO);
12784 GL_DepthMask(writedepth);
12787 if (r_showsurfaces.integer == 3)
12789 rsurface.passcolor4f = NULL;
12791 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12793 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12795 rsurface.passcolor4f = NULL;
12796 rsurface.passcolor4f_vertexbuffer = 0;
12797 rsurface.passcolor4f_bufferoffset = 0;
12799 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12801 qboolean applycolor = true;
12804 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12806 r_refdef.lightmapintensity = 1;
12807 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12808 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12810 else if (FAKELIGHT_ENABLED)
12812 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12814 r_refdef.lightmapintensity = r_fakelight_intensity.value;
12815 RSurf_DrawBatch_GL11_ApplyFakeLight();
12816 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12820 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12822 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12823 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12824 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12827 if(!rsurface.passcolor4f)
12828 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12830 RSurf_DrawBatch_GL11_ApplyAmbient();
12831 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12832 if(r_refdef.fogenabled)
12833 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12834 RSurf_DrawBatch_GL11_ClampColor();
12836 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12837 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12840 else if (!r_refdef.view.showdebug)
12842 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12843 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12844 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12846 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12847 Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12849 R_Mesh_PrepareVertices_Generic_Unlock();
12852 else if (r_showsurfaces.integer == 4)
12854 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12855 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12856 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12858 unsigned char c = vi << 3;
12859 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12860 Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12862 R_Mesh_PrepareVertices_Generic_Unlock();
12865 else if (r_showsurfaces.integer == 2)
12868 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12869 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12870 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12872 unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12873 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12874 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12875 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12876 Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12877 Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12878 Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12880 R_Mesh_PrepareVertices_Generic_Unlock();
12881 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12885 int texturesurfaceindex;
12887 const msurface_t *surface;
12888 unsigned char surfacecolor4ub[4];
12889 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12890 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12892 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12894 surface = texturesurfacelist[texturesurfaceindex];
12895 k = (int)(((size_t)surface) / sizeof(msurface_t));
12896 Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
12897 for (j = 0;j < surface->num_vertices;j++)
12899 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12900 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
12904 R_Mesh_PrepareVertices_Generic_Unlock();
12909 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12912 RSurf_SetupDepthAndCulling();
12913 if (r_showsurfaces.integer)
12915 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12918 switch (vid.renderpath)
12920 case RENDERPATH_GL20:
12921 case RENDERPATH_CGGL:
12922 case RENDERPATH_D3D9:
12923 case RENDERPATH_D3D10:
12924 case RENDERPATH_D3D11:
12925 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12927 case RENDERPATH_GL13:
12928 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12930 case RENDERPATH_GL11:
12931 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12937 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12940 RSurf_SetupDepthAndCulling();
12941 if (r_showsurfaces.integer)
12943 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12946 switch (vid.renderpath)
12948 case RENDERPATH_GL20:
12949 case RENDERPATH_CGGL:
12950 case RENDERPATH_D3D9:
12951 case RENDERPATH_D3D10:
12952 case RENDERPATH_D3D11:
12953 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12955 case RENDERPATH_GL13:
12956 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12958 case RENDERPATH_GL11:
12959 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12965 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12968 int texturenumsurfaces, endsurface;
12969 texture_t *texture;
12970 const msurface_t *surface;
12971 #define MAXBATCH_TRANSPARENTSURFACES 256
12972 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
12974 // if the model is static it doesn't matter what value we give for
12975 // wantnormals and wanttangents, so this logic uses only rules applicable
12976 // to a model, knowing that they are meaningless otherwise
12977 if (ent == r_refdef.scene.worldentity)
12978 RSurf_ActiveWorldEntity();
12979 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12980 RSurf_ActiveModelEntity(ent, false, false, false);
12983 switch (vid.renderpath)
12985 case RENDERPATH_GL20:
12986 case RENDERPATH_CGGL:
12987 case RENDERPATH_D3D9:
12988 case RENDERPATH_D3D10:
12989 case RENDERPATH_D3D11:
12990 RSurf_ActiveModelEntity(ent, true, true, false);
12992 case RENDERPATH_GL13:
12993 case RENDERPATH_GL11:
12994 RSurf_ActiveModelEntity(ent, true, false, false);
12999 if (r_transparentdepthmasking.integer)
13001 qboolean setup = false;
13002 for (i = 0;i < numsurfaces;i = j)
13005 surface = rsurface.modelsurfaces + surfacelist[i];
13006 texture = surface->texture;
13007 rsurface.texture = R_GetCurrentTexture(texture);
13008 rsurface.lightmaptexture = NULL;
13009 rsurface.deluxemaptexture = NULL;
13010 rsurface.uselightmaptexture = false;
13011 // scan ahead until we find a different texture
13012 endsurface = min(i + 1024, numsurfaces);
13013 texturenumsurfaces = 0;
13014 texturesurfacelist[texturenumsurfaces++] = surface;
13015 for (;j < endsurface;j++)
13017 surface = rsurface.modelsurfaces + surfacelist[j];
13018 if (texture != surface->texture)
13020 texturesurfacelist[texturenumsurfaces++] = surface;
13022 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
13024 // render the range of surfaces as depth
13028 GL_ColorMask(0,0,0,0);
13030 GL_DepthTest(true);
13031 GL_BlendFunc(GL_ONE, GL_ZERO);
13032 GL_DepthMask(true);
13033 GL_AlphaTest(false);
13034 R_Mesh_ResetTextureState();
13035 R_SetupShader_DepthOrShadow();
13037 RSurf_SetupDepthAndCulling();
13038 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13039 R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13043 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
13046 for (i = 0;i < numsurfaces;i = j)
13049 surface = rsurface.modelsurfaces + surfacelist[i];
13050 texture = surface->texture;
13051 rsurface.texture = R_GetCurrentTexture(texture);
13052 // scan ahead until we find a different texture
13053 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
13054 texturenumsurfaces = 0;
13055 texturesurfacelist[texturenumsurfaces++] = surface;
13056 if(FAKELIGHT_ENABLED)
13058 rsurface.lightmaptexture = NULL;
13059 rsurface.deluxemaptexture = NULL;
13060 rsurface.uselightmaptexture = false;
13061 for (;j < endsurface;j++)
13063 surface = rsurface.modelsurfaces + surfacelist[j];
13064 if (texture != surface->texture)
13066 texturesurfacelist[texturenumsurfaces++] = surface;
13071 rsurface.lightmaptexture = surface->lightmaptexture;
13072 rsurface.deluxemaptexture = surface->deluxemaptexture;
13073 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
13074 for (;j < endsurface;j++)
13076 surface = rsurface.modelsurfaces + surfacelist[j];
13077 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
13079 texturesurfacelist[texturenumsurfaces++] = surface;
13082 // render the range of surfaces
13083 if (ent == r_refdef.scene.worldentity)
13084 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13086 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13088 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13089 GL_AlphaTest(false);
13092 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
13094 // transparent surfaces get pushed off into the transparent queue
13095 int surfacelistindex;
13096 const msurface_t *surface;
13097 vec3_t tempcenter, center;
13098 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
13100 surface = texturesurfacelist[surfacelistindex];
13101 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
13102 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
13103 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
13104 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
13105 if (queueentity->transparent_offset) // transparent offset
13107 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
13108 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
13109 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
13111 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
13115 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
13117 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
13119 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
13121 RSurf_SetupDepthAndCulling();
13122 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13123 R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13127 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
13129 const entity_render_t *queueentity = r_refdef.scene.worldentity;
13132 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13135 if (!rsurface.texture->currentnumlayers)
13137 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13138 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13140 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13142 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13143 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13144 else if (!rsurface.texture->currentnumlayers)
13146 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13148 // in the deferred case, transparent surfaces were queued during prepass
13149 if (!r_shadow_usingdeferredprepass)
13150 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13154 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13155 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13160 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13163 texture_t *texture;
13164 // break the surface list down into batches by texture and use of lightmapping
13165 for (i = 0;i < numsurfaces;i = j)
13168 // texture is the base texture pointer, rsurface.texture is the
13169 // current frame/skin the texture is directing us to use (for example
13170 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13171 // use skin 1 instead)
13172 texture = surfacelist[i]->texture;
13173 rsurface.texture = R_GetCurrentTexture(texture);
13174 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13176 // if this texture is not the kind we want, skip ahead to the next one
13177 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13181 if(FAKELIGHT_ENABLED || depthonly || prepass)
13183 rsurface.lightmaptexture = NULL;
13184 rsurface.deluxemaptexture = NULL;
13185 rsurface.uselightmaptexture = false;
13186 // simply scan ahead until we find a different texture or lightmap state
13187 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13192 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13193 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13194 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13195 // simply scan ahead until we find a different texture or lightmap state
13196 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13199 // render the range of surfaces
13200 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
13204 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
13208 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13211 if (!rsurface.texture->currentnumlayers)
13213 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13214 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13216 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13218 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13219 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13220 else if (!rsurface.texture->currentnumlayers)
13222 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13224 // in the deferred case, transparent surfaces were queued during prepass
13225 if (!r_shadow_usingdeferredprepass)
13226 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13230 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13231 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13236 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13239 texture_t *texture;
13240 // break the surface list down into batches by texture and use of lightmapping
13241 for (i = 0;i < numsurfaces;i = j)
13244 // texture is the base texture pointer, rsurface.texture is the
13245 // current frame/skin the texture is directing us to use (for example
13246 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13247 // use skin 1 instead)
13248 texture = surfacelist[i]->texture;
13249 rsurface.texture = R_GetCurrentTexture(texture);
13250 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13252 // if this texture is not the kind we want, skip ahead to the next one
13253 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13257 if(FAKELIGHT_ENABLED || depthonly || prepass)
13259 rsurface.lightmaptexture = NULL;
13260 rsurface.deluxemaptexture = NULL;
13261 rsurface.uselightmaptexture = false;
13262 // simply scan ahead until we find a different texture or lightmap state
13263 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13268 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13269 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13270 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13271 // simply scan ahead until we find a different texture or lightmap state
13272 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13275 // render the range of surfaces
13276 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
13280 float locboxvertex3f[6*4*3] =
13282 1,0,1, 1,0,0, 1,1,0, 1,1,1,
13283 0,1,1, 0,1,0, 0,0,0, 0,0,1,
13284 1,1,1, 1,1,0, 0,1,0, 0,1,1,
13285 0,0,1, 0,0,0, 1,0,0, 1,0,1,
13286 0,0,1, 1,0,1, 1,1,1, 0,1,1,
13287 1,0,0, 0,0,0, 0,1,0, 1,1,0
13290 unsigned short locboxelements[6*2*3] =
13295 12,13,14, 12,14,15,
13296 16,17,18, 16,18,19,
13300 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13303 cl_locnode_t *loc = (cl_locnode_t *)ent;
13305 float vertex3f[6*4*3];
13307 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13308 GL_DepthMask(false);
13309 GL_DepthRange(0, 1);
13310 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13311 GL_DepthTest(true);
13312 GL_CullFace(GL_NONE);
13313 R_EntityMatrix(&identitymatrix);
13315 R_Mesh_ResetTextureState();
13317 i = surfacelist[0];
13318 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13319 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13320 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13321 surfacelist[0] < 0 ? 0.5f : 0.125f);
13323 if (VectorCompare(loc->mins, loc->maxs))
13325 VectorSet(size, 2, 2, 2);
13326 VectorMA(loc->mins, -0.5f, size, mins);
13330 VectorCopy(loc->mins, mins);
13331 VectorSubtract(loc->maxs, loc->mins, size);
13334 for (i = 0;i < 6*4*3;)
13335 for (j = 0;j < 3;j++, i++)
13336 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13338 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13339 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13340 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13343 void R_DrawLocs(void)
13346 cl_locnode_t *loc, *nearestloc;
13348 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13349 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13351 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13352 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13356 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13358 if (decalsystem->decals)
13359 Mem_Free(decalsystem->decals);
13360 memset(decalsystem, 0, sizeof(*decalsystem));
13363 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)
13366 tridecal_t *decals;
13369 // expand or initialize the system
13370 if (decalsystem->maxdecals <= decalsystem->numdecals)
13372 decalsystem_t old = *decalsystem;
13373 qboolean useshortelements;
13374 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13375 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13376 decalsystem->decals = (tridecal_t *)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)));
13377 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13378 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13379 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13380 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13381 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13382 if (decalsystem->numdecals)
13383 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13385 Mem_Free(old.decals);
13386 for (i = 0;i < decalsystem->maxdecals*3;i++)
13387 decalsystem->element3i[i] = i;
13388 if (useshortelements)
13389 for (i = 0;i < decalsystem->maxdecals*3;i++)
13390 decalsystem->element3s[i] = i;
13393 // grab a decal and search for another free slot for the next one
13394 decals = decalsystem->decals;
13395 decal = decalsystem->decals + (i = decalsystem->freedecal++);
13396 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13398 decalsystem->freedecal = i;
13399 if (decalsystem->numdecals <= i)
13400 decalsystem->numdecals = i + 1;
13402 // initialize the decal
13404 decal->triangleindex = triangleindex;
13405 decal->surfaceindex = surfaceindex;
13406 decal->decalsequence = decalsequence;
13407 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13408 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13409 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13410 decal->color4ub[0][3] = 255;
13411 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13412 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13413 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13414 decal->color4ub[1][3] = 255;
13415 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13416 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13417 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13418 decal->color4ub[2][3] = 255;
13419 decal->vertex3f[0][0] = v0[0];
13420 decal->vertex3f[0][1] = v0[1];
13421 decal->vertex3f[0][2] = v0[2];
13422 decal->vertex3f[1][0] = v1[0];
13423 decal->vertex3f[1][1] = v1[1];
13424 decal->vertex3f[1][2] = v1[2];
13425 decal->vertex3f[2][0] = v2[0];
13426 decal->vertex3f[2][1] = v2[1];
13427 decal->vertex3f[2][2] = v2[2];
13428 decal->texcoord2f[0][0] = t0[0];
13429 decal->texcoord2f[0][1] = t0[1];
13430 decal->texcoord2f[1][0] = t1[0];
13431 decal->texcoord2f[1][1] = t1[1];
13432 decal->texcoord2f[2][0] = t2[0];
13433 decal->texcoord2f[2][1] = t2[1];
13436 extern cvar_t cl_decals_bias;
13437 extern cvar_t cl_decals_models;
13438 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13439 // baseparms, parms, temps
13440 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)
13445 const float *vertex3f;
13447 float points[2][9][3];
13454 e = rsurface.modelelement3i + 3*triangleindex;
13456 vertex3f = rsurface.modelvertex3f;
13458 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13460 index = 3*e[cornerindex];
13461 VectorCopy(vertex3f + index, v[cornerindex]);
13464 //TriangleNormal(v[0], v[1], v[2], normal);
13465 //if (DotProduct(normal, localnormal) < 0.0f)
13467 // clip by each of the box planes formed from the projection matrix
13468 // if anything survives, we emit the decal
13469 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]);
13472 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]);
13475 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]);
13478 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]);
13481 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]);
13484 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]);
13487 // some part of the triangle survived, so we have to accept it...
13490 // dynamic always uses the original triangle
13492 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13494 index = 3*e[cornerindex];
13495 VectorCopy(vertex3f + index, v[cornerindex]);
13498 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13500 // convert vertex positions to texcoords
13501 Matrix4x4_Transform(projection, v[cornerindex], temp);
13502 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13503 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13504 // calculate distance fade from the projection origin
13505 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13506 f = bound(0.0f, f, 1.0f);
13507 c[cornerindex][0] = r * f;
13508 c[cornerindex][1] = g * f;
13509 c[cornerindex][2] = b * f;
13510 c[cornerindex][3] = 1.0f;
13511 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13514 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);
13516 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13517 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);
13519 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)
13521 matrix4x4_t projection;
13522 decalsystem_t *decalsystem;
13525 const msurface_t *surface;
13526 const msurface_t *surfaces;
13527 const int *surfacelist;
13528 const texture_t *texture;
13530 int numsurfacelist;
13531 int surfacelistindex;
13534 float localorigin[3];
13535 float localnormal[3];
13536 float localmins[3];
13537 float localmaxs[3];
13540 float planes[6][4];
13543 int bih_triangles_count;
13544 int bih_triangles[256];
13545 int bih_surfaces[256];
13547 decalsystem = &ent->decalsystem;
13548 model = ent->model;
13549 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13551 R_DecalSystem_Reset(&ent->decalsystem);
13555 if (!model->brush.data_leafs && !cl_decals_models.integer)
13557 if (decalsystem->model)
13558 R_DecalSystem_Reset(decalsystem);
13562 if (decalsystem->model != model)
13563 R_DecalSystem_Reset(decalsystem);
13564 decalsystem->model = model;
13566 RSurf_ActiveModelEntity(ent, false, false, false);
13568 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13569 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13570 VectorNormalize(localnormal);
13571 localsize = worldsize*rsurface.inversematrixscale;
13572 localmins[0] = localorigin[0] - localsize;
13573 localmins[1] = localorigin[1] - localsize;
13574 localmins[2] = localorigin[2] - localsize;
13575 localmaxs[0] = localorigin[0] + localsize;
13576 localmaxs[1] = localorigin[1] + localsize;
13577 localmaxs[2] = localorigin[2] + localsize;
13579 //VectorCopy(localnormal, planes[4]);
13580 //VectorVectors(planes[4], planes[2], planes[0]);
13581 AnglesFromVectors(angles, localnormal, NULL, false);
13582 AngleVectors(angles, planes[0], planes[2], planes[4]);
13583 VectorNegate(planes[0], planes[1]);
13584 VectorNegate(planes[2], planes[3]);
13585 VectorNegate(planes[4], planes[5]);
13586 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13587 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13588 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13589 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13590 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13591 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13596 matrix4x4_t forwardprojection;
13597 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13598 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13603 float projectionvector[4][3];
13604 VectorScale(planes[0], ilocalsize, projectionvector[0]);
13605 VectorScale(planes[2], ilocalsize, projectionvector[1]);
13606 VectorScale(planes[4], ilocalsize, projectionvector[2]);
13607 projectionvector[0][0] = planes[0][0] * ilocalsize;
13608 projectionvector[0][1] = planes[1][0] * ilocalsize;
13609 projectionvector[0][2] = planes[2][0] * ilocalsize;
13610 projectionvector[1][0] = planes[0][1] * ilocalsize;
13611 projectionvector[1][1] = planes[1][1] * ilocalsize;
13612 projectionvector[1][2] = planes[2][1] * ilocalsize;
13613 projectionvector[2][0] = planes[0][2] * ilocalsize;
13614 projectionvector[2][1] = planes[1][2] * ilocalsize;
13615 projectionvector[2][2] = planes[2][2] * ilocalsize;
13616 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13617 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13618 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13619 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13623 dynamic = model->surfmesh.isanimated;
13624 numsurfacelist = model->nummodelsurfaces;
13625 surfacelist = model->sortedmodelsurfaces;
13626 surfaces = model->data_surfaces;
13629 bih_triangles_count = -1;
13632 if(model->render_bih.numleafs)
13633 bih = &model->render_bih;
13634 else if(model->collision_bih.numleafs)
13635 bih = &model->collision_bih;
13638 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13639 if(bih_triangles_count == 0)
13641 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13643 if(bih_triangles_count > 0)
13645 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13647 surfaceindex = bih_surfaces[triangleindex];
13648 surface = surfaces + surfaceindex;
13649 texture = surface->texture;
13650 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13652 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13654 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13659 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13661 surfaceindex = surfacelist[surfacelistindex];
13662 surface = surfaces + surfaceindex;
13663 // check cull box first because it rejects more than any other check
13664 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13666 // skip transparent surfaces
13667 texture = surface->texture;
13668 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13670 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13672 numtriangles = surface->num_triangles;
13673 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13674 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13679 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13680 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)
13682 int renderentityindex;
13683 float worldmins[3];
13684 float worldmaxs[3];
13685 entity_render_t *ent;
13687 if (!cl_decals_newsystem.integer)
13690 worldmins[0] = worldorigin[0] - worldsize;
13691 worldmins[1] = worldorigin[1] - worldsize;
13692 worldmins[2] = worldorigin[2] - worldsize;
13693 worldmaxs[0] = worldorigin[0] + worldsize;
13694 worldmaxs[1] = worldorigin[1] + worldsize;
13695 worldmaxs[2] = worldorigin[2] + worldsize;
13697 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13699 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13701 ent = r_refdef.scene.entities[renderentityindex];
13702 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13705 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13709 typedef struct r_decalsystem_splatqueue_s
13711 vec3_t worldorigin;
13712 vec3_t worldnormal;
13718 r_decalsystem_splatqueue_t;
13720 int r_decalsystem_numqueued = 0;
13721 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13723 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)
13725 r_decalsystem_splatqueue_t *queue;
13727 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13730 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13731 VectorCopy(worldorigin, queue->worldorigin);
13732 VectorCopy(worldnormal, queue->worldnormal);
13733 Vector4Set(queue->color, r, g, b, a);
13734 Vector4Set(queue->tcrange, s1, t1, s2, t2);
13735 queue->worldsize = worldsize;
13736 queue->decalsequence = cl.decalsequence++;
13739 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13742 r_decalsystem_splatqueue_t *queue;
13744 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13745 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);
13746 r_decalsystem_numqueued = 0;
13749 extern cvar_t cl_decals_max;
13750 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13753 decalsystem_t *decalsystem = &ent->decalsystem;
13760 if (!decalsystem->numdecals)
13763 if (r_showsurfaces.integer)
13766 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13768 R_DecalSystem_Reset(decalsystem);
13772 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13773 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13775 if (decalsystem->lastupdatetime)
13776 frametime = (cl.time - decalsystem->lastupdatetime);
13779 decalsystem->lastupdatetime = cl.time;
13780 decal = decalsystem->decals;
13781 numdecals = decalsystem->numdecals;
13783 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13785 if (decal->color4ub[0][3])
13787 decal->lived += frametime;
13788 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13790 memset(decal, 0, sizeof(*decal));
13791 if (decalsystem->freedecal > i)
13792 decalsystem->freedecal = i;
13796 decal = decalsystem->decals;
13797 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13800 // collapse the array by shuffling the tail decals into the gaps
13803 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13804 decalsystem->freedecal++;
13805 if (decalsystem->freedecal == numdecals)
13807 decal[decalsystem->freedecal] = decal[--numdecals];
13810 decalsystem->numdecals = numdecals;
13812 if (numdecals <= 0)
13814 // if there are no decals left, reset decalsystem
13815 R_DecalSystem_Reset(decalsystem);
13819 extern skinframe_t *decalskinframe;
13820 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13823 decalsystem_t *decalsystem = &ent->decalsystem;
13832 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13835 numdecals = decalsystem->numdecals;
13839 if (r_showsurfaces.integer)
13842 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13844 R_DecalSystem_Reset(decalsystem);
13848 // if the model is static it doesn't matter what value we give for
13849 // wantnormals and wanttangents, so this logic uses only rules applicable
13850 // to a model, knowing that they are meaningless otherwise
13851 if (ent == r_refdef.scene.worldentity)
13852 RSurf_ActiveWorldEntity();
13854 RSurf_ActiveModelEntity(ent, false, false, false);
13856 decalsystem->lastupdatetime = cl.time;
13857 decal = decalsystem->decals;
13859 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13861 // update vertex positions for animated models
13862 v3f = decalsystem->vertex3f;
13863 c4f = decalsystem->color4f;
13864 t2f = decalsystem->texcoord2f;
13865 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13867 if (!decal->color4ub[0][3])
13870 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13873 // update color values for fading decals
13874 if (decal->lived >= cl_decals_time.value)
13876 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13877 alpha *= (1.0f/255.0f);
13880 alpha = 1.0f/255.0f;
13882 c4f[ 0] = decal->color4ub[0][0] * alpha;
13883 c4f[ 1] = decal->color4ub[0][1] * alpha;
13884 c4f[ 2] = decal->color4ub[0][2] * alpha;
13886 c4f[ 4] = decal->color4ub[1][0] * alpha;
13887 c4f[ 5] = decal->color4ub[1][1] * alpha;
13888 c4f[ 6] = decal->color4ub[1][2] * alpha;
13890 c4f[ 8] = decal->color4ub[2][0] * alpha;
13891 c4f[ 9] = decal->color4ub[2][1] * alpha;
13892 c4f[10] = decal->color4ub[2][2] * alpha;
13895 t2f[0] = decal->texcoord2f[0][0];
13896 t2f[1] = decal->texcoord2f[0][1];
13897 t2f[2] = decal->texcoord2f[1][0];
13898 t2f[3] = decal->texcoord2f[1][1];
13899 t2f[4] = decal->texcoord2f[2][0];
13900 t2f[5] = decal->texcoord2f[2][1];
13902 // update vertex positions for animated models
13903 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13905 e = rsurface.modelelement3i + 3*decal->triangleindex;
13906 VectorCopy(rsurface.modelvertexposition[e[0]].vertex3f, v3f);
13907 VectorCopy(rsurface.modelvertexposition[e[1]].vertex3f, v3f + 3);
13908 VectorCopy(rsurface.modelvertexposition[e[2]].vertex3f, v3f + 6);
13912 VectorCopy(decal->vertex3f[0], v3f);
13913 VectorCopy(decal->vertex3f[1], v3f + 3);
13914 VectorCopy(decal->vertex3f[2], v3f + 6);
13917 if (r_refdef.fogenabled)
13919 alpha = RSurf_FogVertex(v3f);
13920 VectorScale(c4f, alpha, c4f);
13921 alpha = RSurf_FogVertex(v3f + 3);
13922 VectorScale(c4f + 4, alpha, c4f + 4);
13923 alpha = RSurf_FogVertex(v3f + 6);
13924 VectorScale(c4f + 8, alpha, c4f + 8);
13935 r_refdef.stats.drawndecals += numtris;
13937 // now render the decals all at once
13938 // (this assumes they all use one particle font texture!)
13939 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);
13940 R_Mesh_ResetTextureState();
13941 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
13942 GL_DepthMask(false);
13943 GL_DepthRange(0, 1);
13944 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
13945 GL_DepthTest(true);
13946 GL_CullFace(GL_NONE);
13947 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
13948 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
13949 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
13953 static void R_DrawModelDecals(void)
13957 // fade faster when there are too many decals
13958 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13959 for (i = 0;i < r_refdef.scene.numentities;i++)
13960 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13962 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
13963 for (i = 0;i < r_refdef.scene.numentities;i++)
13964 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13965 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
13967 R_DecalSystem_ApplySplatEntitiesQueue();
13969 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13970 for (i = 0;i < r_refdef.scene.numentities;i++)
13971 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13973 r_refdef.stats.totaldecals += numdecals;
13975 if (r_showsurfaces.integer)
13978 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
13980 for (i = 0;i < r_refdef.scene.numentities;i++)
13982 if (!r_refdef.viewcache.entityvisible[i])
13984 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13985 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
13989 extern cvar_t mod_collision_bih;
13990 void R_DrawDebugModel(void)
13992 entity_render_t *ent = rsurface.entity;
13993 int i, j, k, l, flagsmask;
13994 const msurface_t *surface;
13995 dp_model_t *model = ent->model;
13998 switch(vid.renderpath)
14000 case RENDERPATH_GL11:
14001 case RENDERPATH_GL13:
14002 case RENDERPATH_GL20:
14003 case RENDERPATH_CGGL:
14005 case RENDERPATH_D3D9:
14006 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14008 case RENDERPATH_D3D10:
14009 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14011 case RENDERPATH_D3D11:
14012 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14016 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
14018 R_Mesh_ResetTextureState();
14019 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
14020 GL_DepthRange(0, 1);
14021 GL_DepthTest(!r_showdisabledepthtest.integer);
14022 GL_DepthMask(false);
14023 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14025 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
14029 qboolean cullbox = ent == r_refdef.scene.worldentity;
14030 const q3mbrush_t *brush;
14031 const bih_t *bih = &model->collision_bih;
14032 const bih_leaf_t *bihleaf;
14033 float vertex3f[3][3];
14034 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
14036 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
14038 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
14040 switch (bihleaf->type)
14043 brush = model->brush.data_brushes + bihleaf->itemindex;
14044 if (brush->colbrushf && brush->colbrushf->numtriangles)
14046 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);
14047 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
14048 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
14051 case BIH_COLLISIONTRIANGLE:
14052 triangleindex = bihleaf->itemindex;
14053 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
14054 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
14055 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
14056 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);
14057 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14058 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14060 case BIH_RENDERTRIANGLE:
14061 triangleindex = bihleaf->itemindex;
14062 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
14063 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
14064 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
14065 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);
14066 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14067 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14073 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
14075 if (r_showtris.integer || r_shownormals.integer)
14077 if (r_showdisabledepthtest.integer)
14079 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14080 GL_DepthMask(false);
14084 GL_BlendFunc(GL_ONE, GL_ZERO);
14085 GL_DepthMask(true);
14087 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
14089 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
14091 rsurface.texture = R_GetCurrentTexture(surface->texture);
14092 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
14094 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
14095 if (r_showtris.value > 0)
14097 if (!rsurface.texture->currentlayers->depthmask)
14098 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
14099 else if (ent == r_refdef.scene.worldentity)
14100 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
14102 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
14103 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
14104 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
14106 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
14109 if (r_shownormals.value < 0)
14111 qglBegin(GL_LINES);
14112 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14114 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14115 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14116 qglVertex3f(v[0], v[1], v[2]);
14117 VectorMA(v, -r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14118 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14119 qglVertex3f(v[0], v[1], v[2]);
14124 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
14126 qglBegin(GL_LINES);
14127 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14129 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14130 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14131 qglVertex3f(v[0], v[1], v[2]);
14132 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14133 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14134 qglVertex3f(v[0], v[1], v[2]);
14138 qglBegin(GL_LINES);
14139 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14141 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14142 GL_Color(0, r_refdef.view.colorscale, 0, 1);
14143 qglVertex3f(v[0], v[1], v[2]);
14144 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
14145 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14146 qglVertex3f(v[0], v[1], v[2]);
14150 qglBegin(GL_LINES);
14151 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14153 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14154 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14155 qglVertex3f(v[0], v[1], v[2]);
14156 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14157 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14158 qglVertex3f(v[0], v[1], v[2]);
14165 rsurface.texture = NULL;
14169 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
14170 int r_maxsurfacelist = 0;
14171 const msurface_t **r_surfacelist = NULL;
14172 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14174 int i, j, endj, flagsmask;
14175 dp_model_t *model = r_refdef.scene.worldmodel;
14176 msurface_t *surfaces;
14177 unsigned char *update;
14178 int numsurfacelist = 0;
14182 if (r_maxsurfacelist < model->num_surfaces)
14184 r_maxsurfacelist = model->num_surfaces;
14186 Mem_Free((msurface_t**)r_surfacelist);
14187 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14190 RSurf_ActiveWorldEntity();
14192 surfaces = model->data_surfaces;
14193 update = model->brushq1.lightmapupdateflags;
14195 // update light styles on this submodel
14196 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14198 model_brush_lightstyleinfo_t *style;
14199 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14201 if (style->value != r_refdef.scene.lightstylevalue[style->style])
14203 int *list = style->surfacelist;
14204 style->value = r_refdef.scene.lightstylevalue[style->style];
14205 for (j = 0;j < style->numsurfaces;j++)
14206 update[list[j]] = true;
14211 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14215 R_DrawDebugModel();
14216 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14220 rsurface.lightmaptexture = NULL;
14221 rsurface.deluxemaptexture = NULL;
14222 rsurface.uselightmaptexture = false;
14223 rsurface.texture = NULL;
14224 rsurface.rtlight = NULL;
14225 numsurfacelist = 0;
14226 // add visible surfaces to draw list
14227 for (i = 0;i < model->nummodelsurfaces;i++)
14229 j = model->sortedmodelsurfaces[i];
14230 if (r_refdef.viewcache.world_surfacevisible[j])
14231 r_surfacelist[numsurfacelist++] = surfaces + j;
14233 // update lightmaps if needed
14234 if (model->brushq1.firstrender)
14236 model->brushq1.firstrender = false;
14237 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14239 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14243 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14244 if (r_refdef.viewcache.world_surfacevisible[j])
14246 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14248 // don't do anything if there were no surfaces
14249 if (!numsurfacelist)
14251 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14254 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14255 GL_AlphaTest(false);
14257 // add to stats if desired
14258 if (r_speeds.integer && !skysurfaces && !depthonly)
14260 r_refdef.stats.world_surfaces += numsurfacelist;
14261 for (j = 0;j < numsurfacelist;j++)
14262 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
14265 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14268 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14270 int i, j, endj, flagsmask;
14271 dp_model_t *model = ent->model;
14272 msurface_t *surfaces;
14273 unsigned char *update;
14274 int numsurfacelist = 0;
14278 if (r_maxsurfacelist < model->num_surfaces)
14280 r_maxsurfacelist = model->num_surfaces;
14282 Mem_Free((msurface_t **)r_surfacelist);
14283 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14286 // if the model is static it doesn't matter what value we give for
14287 // wantnormals and wanttangents, so this logic uses only rules applicable
14288 // to a model, knowing that they are meaningless otherwise
14289 if (ent == r_refdef.scene.worldentity)
14290 RSurf_ActiveWorldEntity();
14291 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14292 RSurf_ActiveModelEntity(ent, false, false, false);
14294 RSurf_ActiveModelEntity(ent, true, true, true);
14295 else if (depthonly)
14297 switch (vid.renderpath)
14299 case RENDERPATH_GL20:
14300 case RENDERPATH_CGGL:
14301 case RENDERPATH_D3D9:
14302 case RENDERPATH_D3D10:
14303 case RENDERPATH_D3D11:
14304 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14306 case RENDERPATH_GL13:
14307 case RENDERPATH_GL11:
14308 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14314 switch (vid.renderpath)
14316 case RENDERPATH_GL20:
14317 case RENDERPATH_CGGL:
14318 case RENDERPATH_D3D9:
14319 case RENDERPATH_D3D10:
14320 case RENDERPATH_D3D11:
14321 RSurf_ActiveModelEntity(ent, true, true, false);
14323 case RENDERPATH_GL13:
14324 case RENDERPATH_GL11:
14325 RSurf_ActiveModelEntity(ent, true, false, false);
14330 surfaces = model->data_surfaces;
14331 update = model->brushq1.lightmapupdateflags;
14333 // update light styles
14334 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14336 model_brush_lightstyleinfo_t *style;
14337 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14339 if (style->value != r_refdef.scene.lightstylevalue[style->style])
14341 int *list = style->surfacelist;
14342 style->value = r_refdef.scene.lightstylevalue[style->style];
14343 for (j = 0;j < style->numsurfaces;j++)
14344 update[list[j]] = true;
14349 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14353 R_DrawDebugModel();
14354 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14358 rsurface.lightmaptexture = NULL;
14359 rsurface.deluxemaptexture = NULL;
14360 rsurface.uselightmaptexture = false;
14361 rsurface.texture = NULL;
14362 rsurface.rtlight = NULL;
14363 numsurfacelist = 0;
14364 // add visible surfaces to draw list
14365 for (i = 0;i < model->nummodelsurfaces;i++)
14366 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14367 // don't do anything if there were no surfaces
14368 if (!numsurfacelist)
14370 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14373 // update lightmaps if needed
14377 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14382 R_BuildLightMap(ent, surfaces + j);
14387 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14389 R_BuildLightMap(ent, surfaces + j);
14390 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14391 GL_AlphaTest(false);
14393 // add to stats if desired
14394 if (r_speeds.integer && !skysurfaces && !depthonly)
14396 r_refdef.stats.entities_surfaces += numsurfacelist;
14397 for (j = 0;j < numsurfacelist;j++)
14398 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14401 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14404 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14406 static texture_t texture;
14407 static msurface_t surface;
14408 const msurface_t *surfacelist = &surface;
14410 // fake enough texture and surface state to render this geometry
14412 texture.update_lastrenderframe = -1; // regenerate this texture
14413 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14414 texture.currentskinframe = skinframe;
14415 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14416 texture.offsetmapping = OFFSETMAPPING_OFF;
14417 texture.offsetscale = 1;
14418 texture.specularscalemod = 1;
14419 texture.specularpowermod = 1;
14421 surface.texture = &texture;
14422 surface.num_triangles = numtriangles;
14423 surface.num_firsttriangle = firsttriangle;
14424 surface.num_vertices = numvertices;
14425 surface.num_firstvertex = firstvertex;
14428 rsurface.texture = R_GetCurrentTexture(surface.texture);
14429 rsurface.lightmaptexture = NULL;
14430 rsurface.deluxemaptexture = NULL;
14431 rsurface.uselightmaptexture = false;
14432 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14435 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)
14437 static msurface_t surface;
14438 const msurface_t *surfacelist = &surface;
14440 // fake enough texture and surface state to render this geometry
14442 surface.texture = texture;
14443 surface.num_triangles = numtriangles;
14444 surface.num_firsttriangle = firsttriangle;
14445 surface.num_vertices = numvertices;
14446 surface.num_firstvertex = firstvertex;
14449 rsurface.texture = R_GetCurrentTexture(surface.texture);
14450 rsurface.lightmaptexture = NULL;
14451 rsurface.deluxemaptexture = NULL;
14452 rsurface.uselightmaptexture = false;
14453 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);