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!)"};
192 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
194 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)"};
196 extern cvar_t v_glslgamma;
198 extern qboolean v_flipped_state;
200 static struct r_bloomstate_s
205 int bloomwidth, bloomheight;
207 int screentexturewidth, screentextureheight;
208 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
210 int bloomtexturewidth, bloomtextureheight;
211 rtexture_t *texture_bloom;
213 // arrays for rendering the screen passes
214 float screentexcoord2f[8];
215 float bloomtexcoord2f[8];
216 float offsettexcoord2f[8];
218 r_viewport_t viewport;
222 r_waterstate_t r_waterstate;
224 /// shadow volume bsp struct with automatically growing nodes buffer
227 rtexture_t *r_texture_blanknormalmap;
228 rtexture_t *r_texture_white;
229 rtexture_t *r_texture_grey128;
230 rtexture_t *r_texture_black;
231 rtexture_t *r_texture_notexture;
232 rtexture_t *r_texture_whitecube;
233 rtexture_t *r_texture_normalizationcube;
234 rtexture_t *r_texture_fogattenuation;
235 rtexture_t *r_texture_fogheighttexture;
236 rtexture_t *r_texture_gammaramps;
237 unsigned int r_texture_gammaramps_serial;
238 //rtexture_t *r_texture_fogintensity;
239 rtexture_t *r_texture_reflectcube;
241 // TODO: hash lookups?
242 typedef struct cubemapinfo_s
249 int r_texture_numcubemaps;
250 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
252 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
253 unsigned int r_numqueries;
254 unsigned int r_maxqueries;
256 typedef struct r_qwskincache_s
258 char name[MAX_QPATH];
259 skinframe_t *skinframe;
263 static r_qwskincache_t *r_qwskincache;
264 static int r_qwskincache_size;
266 /// vertex coordinates for a quad that covers the screen exactly
267 extern const float r_screenvertex3f[12];
268 extern const float r_d3dscreenvertex3f[12];
269 const float r_screenvertex3f[12] =
276 const float r_d3dscreenvertex3f[12] =
284 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
287 for (i = 0;i < verts;i++)
298 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
301 for (i = 0;i < verts;i++)
311 // FIXME: move this to client?
314 if (gamemode == GAME_NEHAHRA)
316 Cvar_Set("gl_fogenable", "0");
317 Cvar_Set("gl_fogdensity", "0.2");
318 Cvar_Set("gl_fogred", "0.3");
319 Cvar_Set("gl_foggreen", "0.3");
320 Cvar_Set("gl_fogblue", "0.3");
322 r_refdef.fog_density = 0;
323 r_refdef.fog_red = 0;
324 r_refdef.fog_green = 0;
325 r_refdef.fog_blue = 0;
326 r_refdef.fog_alpha = 1;
327 r_refdef.fog_start = 0;
328 r_refdef.fog_end = 16384;
329 r_refdef.fog_height = 1<<30;
330 r_refdef.fog_fadedepth = 128;
331 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
334 static void R_BuildBlankTextures(void)
336 unsigned char data[4];
337 data[2] = 128; // normal X
338 data[1] = 128; // normal Y
339 data[0] = 255; // normal Z
340 data[3] = 128; // height
341 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
346 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
351 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
356 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
359 static void R_BuildNoTexture(void)
362 unsigned char pix[16][16][4];
363 // this makes a light grey/dark grey checkerboard texture
364 for (y = 0;y < 16;y++)
366 for (x = 0;x < 16;x++)
368 if ((y < 8) ^ (x < 8))
384 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
387 static void R_BuildWhiteCube(void)
389 unsigned char data[6*1*1*4];
390 memset(data, 255, sizeof(data));
391 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
394 static void R_BuildNormalizationCube(void)
398 vec_t s, t, intensity;
401 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
402 for (side = 0;side < 6;side++)
404 for (y = 0;y < NORMSIZE;y++)
406 for (x = 0;x < NORMSIZE;x++)
408 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
409 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
444 intensity = 127.0f / sqrt(DotProduct(v, v));
445 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
446 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
447 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
448 data[((side*64+y)*64+x)*4+3] = 255;
452 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
456 static void R_BuildFogTexture(void)
460 unsigned char data1[FOGWIDTH][4];
461 //unsigned char data2[FOGWIDTH][4];
464 r_refdef.fogmasktable_start = r_refdef.fog_start;
465 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
466 r_refdef.fogmasktable_range = r_refdef.fogrange;
467 r_refdef.fogmasktable_density = r_refdef.fog_density;
469 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
470 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
472 d = (x * r - r_refdef.fogmasktable_start);
473 if(developer_extra.integer)
474 Con_DPrintf("%f ", d);
476 if (r_fog_exp2.integer)
477 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
479 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
480 if(developer_extra.integer)
481 Con_DPrintf(" : %f ", alpha);
482 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
483 if(developer_extra.integer)
484 Con_DPrintf(" = %f\n", alpha);
485 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
488 for (x = 0;x < FOGWIDTH;x++)
490 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
495 //data2[x][0] = 255 - b;
496 //data2[x][1] = 255 - b;
497 //data2[x][2] = 255 - b;
500 if (r_texture_fogattenuation)
502 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
503 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
507 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
508 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
512 static void R_BuildFogHeightTexture(void)
514 unsigned char *inpixels;
522 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
523 if (r_refdef.fogheighttexturename[0])
524 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
527 r_refdef.fog_height_tablesize = 0;
528 if (r_texture_fogheighttexture)
529 R_FreeTexture(r_texture_fogheighttexture);
530 r_texture_fogheighttexture = NULL;
531 if (r_refdef.fog_height_table2d)
532 Mem_Free(r_refdef.fog_height_table2d);
533 r_refdef.fog_height_table2d = NULL;
534 if (r_refdef.fog_height_table1d)
535 Mem_Free(r_refdef.fog_height_table1d);
536 r_refdef.fog_height_table1d = NULL;
540 r_refdef.fog_height_tablesize = size;
541 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
542 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
543 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
545 // LordHavoc: now the magic - what is that table2d for? it is a cooked
546 // average fog color table accounting for every fog layer between a point
547 // and the camera. (Note: attenuation is handled separately!)
548 for (y = 0;y < size;y++)
550 for (x = 0;x < size;x++)
556 for (j = x;j <= y;j++)
558 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
564 for (j = x;j >= y;j--)
566 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
571 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
572 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
573 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
574 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
577 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
580 //=======================================================================================================================================================
582 static const char *builtinshaderstring =
583 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
584 "// written by Forest 'LordHavoc' Hale\n"
585 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
587 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
590 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
591 "#define USELIGHTMAP\n"
593 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
594 "#define USEEYEVECTOR\n"
597 "#ifdef USESHADOWMAP2D\n"
598 "# ifdef GL_EXT_gpu_shader4\n"
599 "# extension GL_EXT_gpu_shader4 : enable\n"
601 "# ifdef GL_ARB_texture_gather\n"
602 "# extension GL_ARB_texture_gather : enable\n"
604 "# ifdef GL_AMD_texture_texture4\n"
605 "# extension GL_AMD_texture_texture4 : enable\n"
610 "//#ifdef USESHADOWSAMPLER\n"
611 "//# extension GL_ARB_shadow : enable\n"
614 "//#ifdef __GLSL_CG_DATA_TYPES\n"
615 "//# define myhalf half\n"
616 "//# define myhalf2 half2\n"
617 "//# define myhalf3 half3\n"
618 "//# define myhalf4 half4\n"
620 "# define myhalf float\n"
621 "# define myhalf2 vec2\n"
622 "# define myhalf3 vec3\n"
623 "# define myhalf4 vec4\n"
626 "#ifdef VERTEX_SHADER\n"
627 "uniform mat4 ModelViewProjectionMatrix;\n"
630 "#ifdef MODE_DEPTH_OR_SHADOW\n"
631 "#ifdef VERTEX_SHADER\n"
634 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
637 "#else // !MODE_DEPTH_ORSHADOW\n"
642 "#ifdef MODE_SHOWDEPTH\n"
643 "#ifdef VERTEX_SHADER\n"
646 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
647 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
651 "#ifdef FRAGMENT_SHADER\n"
654 " gl_FragColor = gl_Color;\n"
657 "#else // !MODE_SHOWDEPTH\n"
662 "#ifdef MODE_POSTPROCESS\n"
663 "varying vec2 TexCoord1;\n"
664 "varying vec2 TexCoord2;\n"
666 "#ifdef VERTEX_SHADER\n"
669 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
670 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
672 " TexCoord2 = gl_MultiTexCoord4.xy;\n"
677 "#ifdef FRAGMENT_SHADER\n"
678 "uniform sampler2D Texture_First;\n"
680 "uniform sampler2D Texture_Second;\n"
681 "uniform vec4 BloomColorSubtract;\n"
683 "#ifdef USEGAMMARAMPS\n"
684 "uniform sampler2D Texture_GammaRamps;\n"
686 "#ifdef USESATURATION\n"
687 "uniform float Saturation;\n"
689 "#ifdef USEVIEWTINT\n"
690 "uniform vec4 ViewTintColor;\n"
692 "//uncomment these if you want to use them:\n"
693 "uniform vec4 UserVec1;\n"
694 "uniform vec4 UserVec2;\n"
695 "// uniform vec4 UserVec3;\n"
696 "// uniform vec4 UserVec4;\n"
697 "// uniform float ClientTime;\n"
698 "uniform vec2 PixelSize;\n"
701 " gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
703 " gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
705 "#ifdef USEVIEWTINT\n"
706 " gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
709 "#ifdef USEPOSTPROCESSING\n"
710 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
711 "// 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"
712 " float sobel = 1.0;\n"
713 " // vec2 ts = textureSize(Texture_First, 0);\n"
714 " // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
715 " vec2 px = PixelSize;\n"
716 " vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
717 " vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, 0.0)).rgb;\n"
718 " vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
719 " vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
720 " vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x, 0.0)).rgb;\n"
721 " vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
722 " vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
723 " vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2( 0.0,-px.y)).rgb;\n"
724 " vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
725 " vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
726 " vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2( 0.0, px.y)).rgb;\n"
727 " vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
728 " float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
729 " float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
730 " float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
731 " float px4 = 1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
732 " float px5 = 2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
733 " float px6 = 1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
734 " float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
735 " float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
736 " float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
737 " float py4 = 1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
738 " float py5 = 2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
739 " float py6 = 1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
740 " sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
741 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
742 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
743 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
744 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
745 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
746 " gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
747 " gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
750 "#ifdef USESATURATION\n"
751 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
752 " float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
753 " // 'vampire sight' effect, wheres red is compensated\n"
754 " #ifdef SATURATION_REDCOMPENSATE\n"
755 " float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
756 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
757 " gl_FragColor.r += rboost;\n"
759 " // normal desaturation\n"
760 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
761 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
765 "#ifdef USEGAMMARAMPS\n"
766 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
767 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
768 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
772 "#else // !MODE_POSTPROCESS\n"
777 "#ifdef MODE_GENERIC\n"
778 "#ifdef USEDIFFUSE\n"
779 "varying vec2 TexCoord1;\n"
781 "#ifdef USESPECULAR\n"
782 "varying vec2 TexCoord2;\n"
784 "#ifdef VERTEX_SHADER\n"
787 " gl_FrontColor = gl_Color;\n"
788 "#ifdef USEDIFFUSE\n"
789 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
791 "#ifdef USESPECULAR\n"
792 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
794 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
798 "#ifdef FRAGMENT_SHADER\n"
799 "#ifdef USEDIFFUSE\n"
800 "uniform sampler2D Texture_First;\n"
802 "#ifdef USESPECULAR\n"
803 "uniform sampler2D Texture_Second;\n"
808 " gl_FragColor = gl_Color;\n"
809 "#ifdef USEDIFFUSE\n"
810 " gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
813 "#ifdef USESPECULAR\n"
814 " vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
815 "# ifdef USECOLORMAPPING\n"
816 " gl_FragColor *= tex2;\n"
819 " gl_FragColor += tex2;\n"
821 "# ifdef USEVERTEXTEXTUREBLEND\n"
822 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
827 "#else // !MODE_GENERIC\n"
832 "#ifdef MODE_BLOOMBLUR\n"
833 "varying TexCoord;\n"
834 "#ifdef VERTEX_SHADER\n"
837 " gl_FrontColor = gl_Color;\n"
838 " TexCoord = gl_MultiTexCoord0.xy;\n"
839 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
843 "#ifdef FRAGMENT_SHADER\n"
844 "uniform sampler2D Texture_First;\n"
845 "uniform vec4 BloomBlur_Parameters;\n"
850 " vec2 tc = TexCoord;\n"
851 " vec3 color = texture2D(Texture_First, tc).rgb;\n"
852 " tc += BloomBlur_Parameters.xy;\n"
853 " for (i = 1;i < SAMPLES;i++)\n"
855 " color += texture2D(Texture_First, tc).rgb;\n"
856 " tc += BloomBlur_Parameters.xy;\n"
858 " gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
861 "#else // !MODE_BLOOMBLUR\n"
862 "#ifdef MODE_REFRACTION\n"
863 "varying vec2 TexCoord;\n"
864 "varying vec4 ModelViewProjectionPosition;\n"
865 "uniform mat4 TexMatrix;\n"
866 "#ifdef VERTEX_SHADER\n"
870 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
871 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
872 " ModelViewProjectionPosition = gl_Position;\n"
876 "#ifdef FRAGMENT_SHADER\n"
877 "uniform sampler2D Texture_Normal;\n"
878 "uniform sampler2D Texture_Refraction;\n"
879 "uniform sampler2D Texture_Reflection;\n"
881 "uniform vec4 DistortScaleRefractReflect;\n"
882 "uniform vec4 ScreenScaleRefractReflect;\n"
883 "uniform vec4 ScreenCenterRefractReflect;\n"
884 "uniform vec4 RefractColor;\n"
885 "uniform vec4 ReflectColor;\n"
886 "uniform float ReflectFactor;\n"
887 "uniform float ReflectOffset;\n"
891 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
892 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
893 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
894 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
895 " // FIXME temporary hack to detect the case that the reflection\n"
896 " // gets blackened at edges due to leaving the area that contains actual\n"
898 " // Remove this 'ack once we have a better way to stop this thing from\n"
900 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
901 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
902 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
903 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
904 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
905 " gl_FragColor = vec4(texture2D(Texture_Refraction, ScreenTexCoord).rgb, 1.0) * RefractColor;\n"
908 "#else // !MODE_REFRACTION\n"
913 "#ifdef MODE_WATER\n"
914 "varying vec2 TexCoord;\n"
915 "varying vec3 EyeVector;\n"
916 "varying vec4 ModelViewProjectionPosition;\n"
917 "#ifdef VERTEX_SHADER\n"
918 "uniform vec3 EyePosition;\n"
919 "uniform mat4 TexMatrix;\n"
923 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
924 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
925 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
926 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
927 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
928 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
929 " ModelViewProjectionPosition = gl_Position;\n"
933 "#ifdef FRAGMENT_SHADER\n"
934 "uniform sampler2D Texture_Normal;\n"
935 "uniform sampler2D Texture_Refraction;\n"
936 "uniform sampler2D Texture_Reflection;\n"
938 "uniform vec4 DistortScaleRefractReflect;\n"
939 "uniform vec4 ScreenScaleRefractReflect;\n"
940 "uniform vec4 ScreenCenterRefractReflect;\n"
941 "uniform vec4 RefractColor;\n"
942 "uniform vec4 ReflectColor;\n"
943 "uniform float ReflectFactor;\n"
944 "uniform float ReflectOffset;\n"
945 "uniform float ClientTime;\n"
949 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
950 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
951 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
952 " //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
953 " // slight water animation via 2 layer scrolling (todo: tweak)\n"
954 " vec3 normal = texture2D(Texture_Normal, TexCoord + vec2(0.08, 0.08)*ClientTime*0.5).rgb - vec3(1.0);\n"
955 " normal += texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime)*0.75).rgb;\n"
956 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(normal) + vec3(0.15)).xyxy * DistortScaleRefractReflect;\n"
957 " // FIXME temporary hack to detect the case that the reflection\n"
958 " // gets blackened at edges due to leaving the area that contains actual\n"
960 " // Remove this 'ack once we have a better way to stop this thing from\n"
962 " float 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 " f1 *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, 0.01)).rgb) / 0.002);\n"
965 " f1 *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, -0.01)).rgb) / 0.002);\n"
966 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f1);\n"
967 " float 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 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, 0.005)).rgb) / 0.002);\n"
970 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, -0.005)).rgb) / 0.002);\n"
971 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
972 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
973 " gl_FragColor = mix(vec4(texture2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, vec4(texture2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
974 " gl_FragColor.a = f1 + 0.5;\n"
977 "#else // !MODE_WATER\n"
982 "// common definitions between vertex shader and fragment shader:\n"
984 "varying vec2 TexCoord;\n"
985 "#ifdef USEVERTEXTEXTUREBLEND\n"
986 "varying vec2 TexCoord2;\n"
988 "#ifdef USELIGHTMAP\n"
989 "varying vec2 TexCoordLightmap;\n"
992 "#ifdef MODE_LIGHTSOURCE\n"
993 "varying vec3 CubeVector;\n"
996 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
997 "varying vec3 LightVector;\n"
1000 "#ifdef USEEYEVECTOR\n"
1001 "varying vec3 EyeVector;\n"
1004 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
1007 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
1008 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
1009 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
1010 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
1013 "#ifdef USEREFLECTION\n"
1014 "varying vec4 ModelViewProjectionPosition;\n"
1016 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1017 "uniform vec3 LightPosition;\n"
1018 "varying vec4 ModelViewPosition;\n"
1021 "#ifdef MODE_LIGHTSOURCE\n"
1022 "uniform vec3 LightPosition;\n"
1024 "uniform vec3 EyePosition;\n"
1025 "#ifdef MODE_LIGHTDIRECTION\n"
1026 "uniform vec3 LightDir;\n"
1028 "uniform vec4 FogPlane;\n"
1030 "#ifdef USESHADOWMAPORTHO\n"
1031 "varying vec3 ShadowMapTC;\n"
1038 "// 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"
1040 "// fragment shader specific:\n"
1041 "#ifdef FRAGMENT_SHADER\n"
1043 "uniform sampler2D Texture_Normal;\n"
1044 "uniform sampler2D Texture_Color;\n"
1045 "uniform sampler2D Texture_Gloss;\n"
1047 "uniform sampler2D Texture_Glow;\n"
1049 "#ifdef USEVERTEXTEXTUREBLEND\n"
1050 "uniform sampler2D Texture_SecondaryNormal;\n"
1051 "uniform sampler2D Texture_SecondaryColor;\n"
1052 "uniform sampler2D Texture_SecondaryGloss;\n"
1054 "uniform sampler2D Texture_SecondaryGlow;\n"
1057 "#ifdef USECOLORMAPPING\n"
1058 "uniform sampler2D Texture_Pants;\n"
1059 "uniform sampler2D Texture_Shirt;\n"
1062 "#ifdef USEFOGHEIGHTTEXTURE\n"
1063 "uniform sampler2D Texture_FogHeightTexture;\n"
1065 "uniform sampler2D Texture_FogMask;\n"
1067 "#ifdef USELIGHTMAP\n"
1068 "uniform sampler2D Texture_Lightmap;\n"
1070 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1071 "uniform sampler2D Texture_Deluxemap;\n"
1073 "#ifdef USEREFLECTION\n"
1074 "uniform sampler2D Texture_Reflection;\n"
1077 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1078 "uniform sampler2D Texture_ScreenDepth;\n"
1079 "uniform sampler2D Texture_ScreenNormalMap;\n"
1081 "#ifdef USEDEFERREDLIGHTMAP\n"
1082 "uniform sampler2D Texture_ScreenDiffuse;\n"
1083 "uniform sampler2D Texture_ScreenSpecular;\n"
1086 "uniform myhalf3 Color_Pants;\n"
1087 "uniform myhalf3 Color_Shirt;\n"
1088 "uniform myhalf3 FogColor;\n"
1091 "uniform float FogRangeRecip;\n"
1092 "uniform float FogPlaneViewDist;\n"
1093 "uniform float FogHeightFade;\n"
1094 "vec3 FogVertex(vec3 surfacecolor)\n"
1096 " vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1097 " float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1099 "#ifdef USEFOGHEIGHTTEXTURE\n"
1100 " vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1101 " fogfrac = fogheightpixel.a;\n"
1102 " return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1104 "# ifdef USEFOGOUTSIDE\n"
1105 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1107 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1109 " return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1114 "#ifdef USEOFFSETMAPPING\n"
1115 "uniform float OffsetMapping_Scale;\n"
1116 "vec2 OffsetMapping(vec2 TexCoord)\n"
1118 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1119 " // 14 sample relief mapping: linear search and then binary search\n"
1120 " // this basically steps forward a small amount repeatedly until it finds\n"
1121 " // itself inside solid, then jitters forward and back using decreasing\n"
1122 " // amounts to find the impact\n"
1123 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1124 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1125 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1126 " vec3 RT = vec3(TexCoord, 1);\n"
1127 " OffsetVector *= 0.1;\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);\n"
1136 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1137 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
1138 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
1139 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
1140 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
1141 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1144 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1145 " // this basically moves forward the full distance, and then backs up based\n"
1146 " // on height of samples\n"
1147 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1148 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1149 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1150 " TexCoord += OffsetVector;\n"
1151 " OffsetVector *= 0.333;\n"
1152 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1153 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1154 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1155 " return TexCoord;\n"
1158 "#endif // USEOFFSETMAPPING\n"
1160 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1161 "uniform sampler2D Texture_Attenuation;\n"
1162 "uniform samplerCube Texture_Cube;\n"
1165 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1167 "#ifdef USESHADOWMAP2D\n"
1168 "# ifdef USESHADOWSAMPLER\n"
1169 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1171 "uniform sampler2D Texture_ShadowMap2D;\n"
1175 "#ifdef USESHADOWMAPVSDCT\n"
1176 "uniform samplerCube Texture_CubeProjection;\n"
1179 "#if defined(USESHADOWMAP2D)\n"
1180 "uniform vec2 ShadowMap_TextureScale;\n"
1181 "uniform vec4 ShadowMap_Parameters;\n"
1184 "#if defined(USESHADOWMAP2D)\n"
1185 "# ifdef USESHADOWMAPORTHO\n"
1186 "# define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1188 "# ifdef USESHADOWMAPVSDCT\n"
1189 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1191 " vec3 adir = abs(dir);\n"
1192 " vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1193 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1194 " return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1197 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1199 " vec3 adir = abs(dir);\n"
1200 " float ma = adir.z;\n"
1201 " vec4 proj = vec4(dir, 2.5);\n"
1202 " if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1203 " if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1204 " vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1205 " 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"
1209 "#endif // defined(USESHADOWMAP2D)\n"
1211 "# ifdef USESHADOWMAP2D\n"
1212 "float ShadowMapCompare(vec3 dir)\n"
1214 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1217 "# ifdef USESHADOWSAMPLER\n"
1218 "# ifdef USESHADOWMAPPCF\n"
1219 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1220 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1221 " 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"
1223 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1226 "# ifdef USESHADOWMAPPCF\n"
1227 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1228 "# ifdef GL_ARB_texture_gather\n"
1229 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1231 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1233 " vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1234 "# if USESHADOWMAPPCF > 1\n"
1235 " vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1236 " vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1237 " vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1238 " vec4 group4 = step(shadowmaptc.z, texval(-2.0, 0.0));\n"
1239 " vec4 group5 = step(shadowmaptc.z, texval( 0.0, 0.0));\n"
1240 " vec4 group6 = step(shadowmaptc.z, texval( 2.0, 0.0));\n"
1241 " vec4 group7 = step(shadowmaptc.z, texval(-2.0, 2.0));\n"
1242 " vec4 group8 = step(shadowmaptc.z, texval( 0.0, 2.0));\n"
1243 " vec4 group9 = step(shadowmaptc.z, texval( 2.0, 2.0));\n"
1244 " vec4 locols = vec4(group1.ab, group3.ab);\n"
1245 " vec4 hicols = vec4(group7.rg, group9.rg);\n"
1246 " locols.yz += group2.ab;\n"
1247 " hicols.yz += group8.rg;\n"
1248 " vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1249 " vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1250 " mix(locols, hicols, offset.y);\n"
1251 " vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1252 " cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1253 " f = dot(cols, vec4(1.0/25.0));\n"
1255 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1256 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1257 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1258 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1259 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1260 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1261 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1264 "# ifdef GL_EXT_gpu_shader4\n"
1265 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1267 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1269 "# if USESHADOWMAPPCF > 1\n"
1270 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1271 " center *= ShadowMap_TextureScale;\n"
1272 " 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"
1273 " 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"
1274 " 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"
1275 " 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"
1276 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1277 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1279 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1280 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1281 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1282 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1283 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1284 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1288 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1291 "# ifdef USESHADOWMAPORTHO\n"
1292 " return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1298 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1299 "#endif // FRAGMENT_SHADER\n"
1304 "#ifdef MODE_DEFERREDGEOMETRY\n"
1305 "#ifdef VERTEX_SHADER\n"
1306 "uniform mat4 TexMatrix;\n"
1307 "#ifdef USEVERTEXTEXTUREBLEND\n"
1308 "uniform mat4 BackgroundTexMatrix;\n"
1310 "uniform mat4 ModelViewMatrix;\n"
1313 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1314 "#ifdef USEVERTEXTEXTUREBLEND\n"
1315 " gl_FrontColor = gl_Color;\n"
1316 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1319 " // transform unnormalized eye direction into tangent space\n"
1320 "#ifdef USEOFFSETMAPPING\n"
1321 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1322 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1323 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1324 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1327 " VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1328 " VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1329 " VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1330 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1332 "#endif // VERTEX_SHADER\n"
1334 "#ifdef FRAGMENT_SHADER\n"
1337 "#ifdef USEOFFSETMAPPING\n"
1338 " // apply offsetmapping\n"
1339 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1340 "#define TexCoord TexCoordOffset\n"
1343 "#ifdef USEALPHAKILL\n"
1344 " if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1348 "#ifdef USEVERTEXTEXTUREBLEND\n"
1349 " float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1350 " float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1351 " //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1352 " //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1355 "#ifdef USEVERTEXTEXTUREBLEND\n"
1356 " vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1357 " float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1359 " vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1360 " float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1363 " gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1365 "#endif // FRAGMENT_SHADER\n"
1366 "#else // !MODE_DEFERREDGEOMETRY\n"
1371 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1372 "#ifdef VERTEX_SHADER\n"
1373 "uniform mat4 ModelViewMatrix;\n"
1376 " ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1377 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1379 "#endif // VERTEX_SHADER\n"
1381 "#ifdef FRAGMENT_SHADER\n"
1382 "uniform mat4 ViewToLight;\n"
1383 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1384 "uniform vec2 ScreenToDepth;\n"
1385 "uniform myhalf3 DeferredColor_Ambient;\n"
1386 "uniform myhalf3 DeferredColor_Diffuse;\n"
1387 "#ifdef USESPECULAR\n"
1388 "uniform myhalf3 DeferredColor_Specular;\n"
1389 "uniform myhalf SpecularPower;\n"
1391 "uniform myhalf2 PixelToScreenTexCoord;\n"
1394 " // calculate viewspace pixel position\n"
1395 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1397 " position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1398 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1399 " // decode viewspace pixel normal\n"
1400 " myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1401 " myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1402 " // surfacenormal = pixel normal in viewspace\n"
1403 " // LightVector = pixel to light in viewspace\n"
1404 " // CubeVector = position in lightspace\n"
1405 " // eyevector = pixel to view in viewspace\n"
1406 " vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1407 " myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1408 "#ifdef USEDIFFUSE\n"
1409 " // calculate diffuse shading\n"
1410 " myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1411 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1413 "#ifdef USESPECULAR\n"
1414 " // calculate directional shading\n"
1415 " vec3 eyevector = position * -1.0;\n"
1416 "# ifdef USEEXACTSPECULARMATH\n"
1417 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1419 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1420 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1424 "#if defined(USESHADOWMAP2D)\n"
1425 " fade *= ShadowMapCompare(CubeVector);\n"
1428 "#ifdef USEDIFFUSE\n"
1429 " gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1431 " gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1433 "#ifdef USESPECULAR\n"
1434 " gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1436 " gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1439 "# ifdef USECUBEFILTER\n"
1440 " vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1441 " gl_FragData[0].rgb *= cubecolor;\n"
1442 " gl_FragData[1].rgb *= cubecolor;\n"
1445 "#endif // FRAGMENT_SHADER\n"
1446 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1451 "#ifdef VERTEX_SHADER\n"
1452 "uniform mat4 TexMatrix;\n"
1453 "#ifdef USEVERTEXTEXTUREBLEND\n"
1454 "uniform mat4 BackgroundTexMatrix;\n"
1456 "#ifdef MODE_LIGHTSOURCE\n"
1457 "uniform mat4 ModelToLight;\n"
1459 "#ifdef USESHADOWMAPORTHO\n"
1460 "uniform mat4 ShadowMapMatrix;\n"
1464 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1465 " gl_FrontColor = gl_Color;\n"
1467 " // copy the surface texcoord\n"
1468 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1469 "#ifdef USEVERTEXTEXTUREBLEND\n"
1470 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1472 "#ifdef USELIGHTMAP\n"
1473 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1476 "#ifdef MODE_LIGHTSOURCE\n"
1477 " // transform vertex position into light attenuation/cubemap space\n"
1478 " // (-1 to +1 across the light box)\n"
1479 " CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1481 "# ifdef USEDIFFUSE\n"
1482 " // transform unnormalized light direction into tangent space\n"
1483 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
1484 " // normalize it per pixel)\n"
1485 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1486 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1487 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1488 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1492 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1493 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1494 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1495 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1498 " // transform unnormalized eye direction into tangent space\n"
1499 "#ifdef USEEYEVECTOR\n"
1500 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1501 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1502 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1503 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1507 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1508 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1511 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1512 " VectorS = gl_MultiTexCoord1.xyz;\n"
1513 " VectorT = gl_MultiTexCoord2.xyz;\n"
1514 " VectorR = gl_MultiTexCoord3.xyz;\n"
1517 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1518 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1520 "#ifdef USESHADOWMAPORTHO\n"
1521 " ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1524 "#ifdef USEREFLECTION\n"
1525 " ModelViewProjectionPosition = gl_Position;\n"
1528 "#endif // VERTEX_SHADER\n"
1533 "#ifdef FRAGMENT_SHADER\n"
1534 "#ifdef USEDEFERREDLIGHTMAP\n"
1535 "uniform myhalf2 PixelToScreenTexCoord;\n"
1536 "uniform myhalf3 DeferredMod_Diffuse;\n"
1537 "uniform myhalf3 DeferredMod_Specular;\n"
1539 "uniform myhalf3 Color_Ambient;\n"
1540 "uniform myhalf3 Color_Diffuse;\n"
1541 "uniform myhalf3 Color_Specular;\n"
1542 "uniform myhalf SpecularPower;\n"
1544 "uniform myhalf3 Color_Glow;\n"
1546 "uniform myhalf Alpha;\n"
1547 "#ifdef USEREFLECTION\n"
1548 "uniform vec4 DistortScaleRefractReflect;\n"
1549 "uniform vec4 ScreenScaleRefractReflect;\n"
1550 "uniform vec4 ScreenCenterRefractReflect;\n"
1551 "uniform myhalf4 ReflectColor;\n"
1553 "#ifdef USEREFLECTCUBE\n"
1554 "uniform mat4 ModelToReflectCube;\n"
1555 "uniform sampler2D Texture_ReflectMask;\n"
1556 "uniform samplerCube Texture_ReflectCube;\n"
1558 "#ifdef MODE_LIGHTDIRECTION\n"
1559 "uniform myhalf3 LightColor;\n"
1561 "#ifdef MODE_LIGHTSOURCE\n"
1562 "uniform myhalf3 LightColor;\n"
1566 "#ifdef USEOFFSETMAPPING\n"
1567 " // apply offsetmapping\n"
1568 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1569 "#define TexCoord TexCoordOffset\n"
1572 " // combine the diffuse textures (base, pants, shirt)\n"
1573 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1574 "#ifdef USEALPHAKILL\n"
1575 " if (color.a < 0.5)\n"
1578 " color.a *= Alpha;\n"
1579 "#ifdef USECOLORMAPPING\n"
1580 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1582 "#ifdef USEVERTEXTEXTUREBLEND\n"
1583 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1584 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1585 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1586 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1588 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1591 " // get the surface normal\n"
1592 "#ifdef USEVERTEXTEXTUREBLEND\n"
1593 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1595 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1598 " // get the material colors\n"
1599 " myhalf3 diffusetex = color.rgb;\n"
1600 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1601 "# ifdef USEVERTEXTEXTUREBLEND\n"
1602 " myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1604 " myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1608 "#ifdef USEREFLECTCUBE\n"
1609 " vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1610 " vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1611 " vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1612 " diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1618 "#ifdef MODE_LIGHTSOURCE\n"
1619 " // light source\n"
1620 "#ifdef USEDIFFUSE\n"
1621 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1622 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1623 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1624 "#ifdef USESPECULAR\n"
1625 "#ifdef USEEXACTSPECULARMATH\n"
1626 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1628 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1629 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1631 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1634 " color.rgb = diffusetex * Color_Ambient;\n"
1636 " color.rgb *= LightColor;\n"
1637 " color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1638 "#if defined(USESHADOWMAP2D)\n"
1639 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1641 "# ifdef USECUBEFILTER\n"
1642 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1644 "#endif // MODE_LIGHTSOURCE\n"
1649 "#ifdef MODE_LIGHTDIRECTION\n"
1651 "#ifdef USEDIFFUSE\n"
1652 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1654 "#define lightcolor LightColor\n"
1655 "#endif // MODE_LIGHTDIRECTION\n"
1656 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1658 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1659 " myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1660 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1661 " // convert modelspace light vector to tangentspace\n"
1662 " myhalf3 lightnormal;\n"
1663 " lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1664 " lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1665 " lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1666 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1667 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1668 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1669 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1670 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1671 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1672 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1673 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1674 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1675 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1676 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1677 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1679 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1680 " myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1681 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1687 "#ifdef MODE_FAKELIGHT\n"
1689 "myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
1690 "myhalf3 lightcolor = myhalf3(1.0);\n"
1691 "#endif // MODE_FAKELIGHT\n"
1696 "#ifdef MODE_LIGHTMAP\n"
1697 " color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1698 "#endif // MODE_LIGHTMAP\n"
1699 "#ifdef MODE_VERTEXCOLOR\n"
1700 " color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1701 "#endif // MODE_VERTEXCOLOR\n"
1702 "#ifdef MODE_FLATCOLOR\n"
1703 " color.rgb = diffusetex * Color_Ambient;\n"
1704 "#endif // MODE_FLATCOLOR\n"
1710 "# ifdef USEDIFFUSE\n"
1711 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1712 "# ifdef USESPECULAR\n"
1713 "# ifdef USEEXACTSPECULARMATH\n"
1714 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1716 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1717 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1719 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1721 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1724 " color.rgb = diffusetex * Color_Ambient;\n"
1728 "#ifdef USESHADOWMAPORTHO\n"
1729 " color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1732 "#ifdef USEDEFERREDLIGHTMAP\n"
1733 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1734 " color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1735 " color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1739 "#ifdef USEVERTEXTEXTUREBLEND\n"
1740 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1742 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1747 " color.rgb = FogVertex(color.rgb);\n"
1750 " // 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"
1751 "#ifdef USEREFLECTION\n"
1752 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1753 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1754 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1755 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1756 " // FIXME temporary hack to detect the case that the reflection\n"
1757 " // gets blackened at edges due to leaving the area that contains actual\n"
1759 " // Remove this 'ack once we have a better way to stop this thing from\n"
1761 " float 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 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1764 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1765 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1766 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1769 " gl_FragColor = vec4(color);\n"
1771 "#endif // FRAGMENT_SHADER\n"
1773 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1774 "#endif // !MODE_DEFERREDGEOMETRY\n"
1775 "#endif // !MODE_WATER\n"
1776 "#endif // !MODE_REFRACTION\n"
1777 "#endif // !MODE_BLOOMBLUR\n"
1778 "#endif // !MODE_GENERIC\n"
1779 "#endif // !MODE_POSTPROCESS\n"
1780 "#endif // !MODE_SHOWDEPTH\n"
1781 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1785 =========================================================================================================================================================
1789 =========================================================================================================================================================
1793 =========================================================================================================================================================
1797 =========================================================================================================================================================
1801 =========================================================================================================================================================
1805 =========================================================================================================================================================
1809 =========================================================================================================================================================
1812 const char *builtincgshaderstring =
1813 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1814 "// written by Forest 'LordHavoc' Hale\n"
1815 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1817 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1818 "#if defined(USEREFLECTION)\n"
1819 "#undef USESHADOWMAPORTHO\n"
1822 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1825 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1826 "#define USELIGHTMAP\n"
1828 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
1829 "#define USEEYEVECTOR\n"
1832 "#ifdef FRAGMENT_SHADER\n"
1834 "//#undef USESHADOWMAPPCF\n"
1835 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1836 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1838 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1842 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1843 "#ifdef VERTEX_SHADER\n"
1846 "float4 gl_Vertex : POSITION,\n"
1847 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1848 "out float4 gl_Position : POSITION,\n"
1849 "out float Depth : TEXCOORD0\n"
1852 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1853 " Depth = gl_Position.z;\n"
1857 "#ifdef FRAGMENT_SHADER\n"
1860 "float Depth : TEXCOORD0,\n"
1861 "out float4 gl_FragColor : COLOR\n"
1864 "// float3 temp = float3(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0));\n"
1865 " float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
1866 " temp.yz -= floor(temp.yz);\n"
1867 " gl_FragColor = temp;\n"
1868 "// gl_FragColor = float4(Depth,0,0,0);\n"
1871 "#else // !MODE_DEPTH_ORSHADOW\n"
1876 "#ifdef MODE_SHOWDEPTH\n"
1877 "#ifdef VERTEX_SHADER\n"
1880 "float4 gl_Vertex : POSITION,\n"
1881 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1882 "out float4 gl_Position : POSITION,\n"
1883 "out float4 gl_FrontColor : COLOR0\n"
1886 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1887 " gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1891 "#ifdef FRAGMENT_SHADER\n"
1894 "float4 gl_FrontColor : COLOR0,\n"
1895 "out float4 gl_FragColor : COLOR\n"
1898 " gl_FragColor = gl_FrontColor;\n"
1901 "#else // !MODE_SHOWDEPTH\n"
1906 "#ifdef MODE_POSTPROCESS\n"
1908 "#ifdef VERTEX_SHADER\n"
1911 "float4 gl_Vertex : POSITION,\n"
1912 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1913 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1914 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1915 "out float4 gl_Position : POSITION,\n"
1916 "out float2 TexCoord1 : TEXCOORD0,\n"
1917 "out float2 TexCoord2 : TEXCOORD1\n"
1920 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1921 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
1923 " TexCoord2 = gl_MultiTexCoord4.xy;\n"
1928 "#ifdef FRAGMENT_SHADER\n"
1931 "float2 TexCoord1 : TEXCOORD0,\n"
1932 "float2 TexCoord2 : TEXCOORD1,\n"
1933 "uniform sampler Texture_First : register(s0),\n"
1935 "uniform sampler Texture_Second : register(s1),\n"
1937 "#ifdef USEGAMMARAMPS\n"
1938 "uniform sampler Texture_GammaRamps : register(s2),\n"
1940 "#ifdef USESATURATION\n"
1941 "uniform float Saturation : register(c30),\n"
1943 "#ifdef USEVIEWTINT\n"
1944 "uniform float4 ViewTintColor : register(c41),\n"
1946 "uniform float4 UserVec1 : register(c37),\n"
1947 "uniform float4 UserVec2 : register(c38),\n"
1948 "uniform float4 UserVec3 : register(c39),\n"
1949 "uniform float4 UserVec4 : register(c40),\n"
1950 "uniform float ClientTime : register(c2),\n"
1951 "uniform float2 PixelSize : register(c25),\n"
1952 "uniform float4 BloomColorSubtract : register(c43),\n"
1953 "out float4 gl_FragColor : COLOR\n"
1956 " gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1958 " gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
1960 "#ifdef USEVIEWTINT\n"
1961 " gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1964 "#ifdef USEPOSTPROCESSING\n"
1965 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1966 "// 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"
1967 " float sobel = 1.0;\n"
1968 " // float2 ts = textureSize(Texture_First, 0);\n"
1969 " // float2 px = float2(1/ts.x, 1/ts.y);\n"
1970 " float2 px = PixelSize;\n"
1971 " float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1972 " float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x, 0.0)).rgb;\n"
1973 " float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1974 " float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1975 " float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x, 0.0)).rgb;\n"
1976 " float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1977 " float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1978 " float3 y2 = tex2D(Texture_First, TexCoord1 + float2( 0.0,-px.y)).rgb;\n"
1979 " float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1980 " float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1981 " float3 y5 = tex2D(Texture_First, TexCoord1 + float2( 0.0, px.y)).rgb;\n"
1982 " float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1983 " float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
1984 " float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
1985 " float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
1986 " float px4 = 1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
1987 " float px5 = 2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
1988 " float px6 = 1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
1989 " float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
1990 " float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
1991 " float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
1992 " float py4 = 1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
1993 " float py5 = 2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
1994 " float py6 = 1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
1995 " sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
1996 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1997 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1998 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1999 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107, 0.707107)) * UserVec1.y;\n"
2000 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990, 0.891007)) * UserVec1.y;\n"
2001 " gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2002 " gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2005 "#ifdef USESATURATION\n"
2006 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2007 " float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2008 " // 'vampire sight' effect, wheres red is compensated\n"
2009 " #ifdef SATURATION_REDCOMPENSATE\n"
2010 " float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
2011 " gl_FragColor.rgb = mix(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2012 " gl_FragColor.r += r;\n"
2014 " // normal desaturation\n"
2015 " //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2016 " gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2020 "#ifdef USEGAMMARAMPS\n"
2021 " gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2022 " gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2023 " gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2027 "#else // !MODE_POSTPROCESS\n"
2032 "#ifdef MODE_GENERIC\n"
2033 "#ifdef VERTEX_SHADER\n"
2036 "float4 gl_Vertex : POSITION,\n"
2037 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2038 "float4 gl_Color : COLOR0,\n"
2039 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2040 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2041 "out float4 gl_Position : POSITION,\n"
2042 "#ifdef USEDIFFUSE\n"
2043 "out float2 TexCoord1 : TEXCOORD0,\n"
2045 "#ifdef USESPECULAR\n"
2046 "out float2 TexCoord2 : TEXCOORD1,\n"
2048 "out float4 gl_FrontColor : COLOR\n"
2052 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2054 " gl_FrontColor = gl_Color; // Cg is forward\n"
2056 "#ifdef USEDIFFUSE\n"
2057 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
2059 "#ifdef USESPECULAR\n"
2060 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
2062 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2066 "#ifdef FRAGMENT_SHADER\n"
2070 "float4 gl_FrontColor : COLOR0,\n"
2071 "float2 TexCoord1 : TEXCOORD0,\n"
2072 "float2 TexCoord2 : TEXCOORD1,\n"
2073 "#ifdef USEDIFFUSE\n"
2074 "uniform sampler Texture_First : register(s0),\n"
2076 "#ifdef USESPECULAR\n"
2077 "uniform sampler Texture_Second : register(s1),\n"
2079 "out float4 gl_FragColor : COLOR\n"
2082 " gl_FragColor = gl_FrontColor;\n"
2083 "#ifdef USEDIFFUSE\n"
2084 " gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2087 "#ifdef USESPECULAR\n"
2088 " float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2089 "# ifdef USECOLORMAPPING\n"
2090 " gl_FragColor *= tex2;\n"
2093 " gl_FragColor += tex2;\n"
2095 "# ifdef USEVERTEXTEXTUREBLEND\n"
2096 " gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2101 "#else // !MODE_GENERIC\n"
2106 "#ifdef MODE_BLOOMBLUR\n"
2107 "#ifdef VERTEX_SHADER\n"
2110 "float4 gl_Vertex : POSITION,\n"
2111 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2112 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2113 "out float4 gl_Position : POSITION,\n"
2114 "out float2 TexCoord : TEXCOORD0\n"
2117 " TexCoord = gl_MultiTexCoord0.xy;\n"
2118 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2122 "#ifdef FRAGMENT_SHADER\n"
2126 "float2 TexCoord : TEXCOORD0,\n"
2127 "uniform sampler Texture_First : register(s0),\n"
2128 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2129 "out float4 gl_FragColor : COLOR\n"
2133 " float2 tc = TexCoord;\n"
2134 " float3 color = tex2D(Texture_First, tc).rgb;\n"
2135 " tc += BloomBlur_Parameters.xy;\n"
2136 " for (i = 1;i < SAMPLES;i++)\n"
2138 " color += tex2D(Texture_First, tc).rgb;\n"
2139 " tc += BloomBlur_Parameters.xy;\n"
2141 " gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2144 "#else // !MODE_BLOOMBLUR\n"
2145 "#ifdef MODE_REFRACTION\n"
2146 "#ifdef VERTEX_SHADER\n"
2149 "float4 gl_Vertex : POSITION,\n"
2150 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2151 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2152 "uniform float4x4 TexMatrix : register(c0),\n"
2153 "uniform float3 EyePosition : register(c24),\n"
2154 "out float4 gl_Position : POSITION,\n"
2155 "out float2 TexCoord : TEXCOORD0,\n"
2156 "out float3 EyeVector : TEXCOORD1,\n"
2157 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2160 " TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2161 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2162 " ModelViewProjectionPosition = gl_Position;\n"
2166 "#ifdef FRAGMENT_SHADER\n"
2169 "float2 TexCoord : TEXCOORD0,\n"
2170 "float3 EyeVector : TEXCOORD1,\n"
2171 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2172 "uniform sampler Texture_Normal : register(s0),\n"
2173 "uniform sampler Texture_Refraction : register(s3),\n"
2174 "uniform sampler Texture_Reflection : register(s7),\n"
2175 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2176 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2177 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2178 "uniform float4 RefractColor : register(c29),\n"
2179 "out float4 gl_FragColor : COLOR\n"
2182 " float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2183 " //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"
2184 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2185 " float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.xy;\n"
2186 " // FIXME temporary hack to detect the case that the reflection\n"
2187 " // gets blackened at edges due to leaving the area that contains actual\n"
2189 " // Remove this 'ack once we have a better way to stop this thing from\n"
2191 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2192 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2193 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2194 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2195 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2196 " gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
2199 "#else // !MODE_REFRACTION\n"
2204 "#ifdef MODE_WATER\n"
2205 "#ifdef VERTEX_SHADER\n"
2209 "float4 gl_Vertex : POSITION,\n"
2210 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2211 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2212 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2213 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2214 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2215 "uniform float4x4 TexMatrix : register(c0),\n"
2216 "uniform float3 EyePosition : register(c24),\n"
2217 "out float4 gl_Position : POSITION,\n"
2218 "out float2 TexCoord : TEXCOORD0,\n"
2219 "out float3 EyeVector : TEXCOORD1,\n"
2220 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2223 " TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2224 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2225 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2226 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2227 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2228 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2229 " ModelViewProjectionPosition = gl_Position;\n"
2233 "#ifdef FRAGMENT_SHADER\n"
2236 "float2 TexCoord : TEXCOORD0,\n"
2237 "float3 EyeVector : TEXCOORD1,\n"
2238 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2239 "uniform sampler Texture_Normal : register(s0),\n"
2240 "uniform sampler Texture_Refraction : register(s3),\n"
2241 "uniform sampler Texture_Reflection : register(s7),\n"
2242 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2243 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2244 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2245 "uniform float4 RefractColor : register(c29),\n"
2246 "uniform float4 ReflectColor : register(c26),\n"
2247 "uniform float ReflectFactor : register(c27),\n"
2248 "uniform float ReflectOffset : register(c28),\n"
2249 "out float4 gl_FragColor : COLOR\n"
2252 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2253 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2254 " float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2255 " //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2256 " float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2257 " // FIXME temporary hack to detect the case that the reflection\n"
2258 " // gets blackened at edges due to leaving the area that contains actual\n"
2260 " // Remove this 'ack once we have a better way to stop this thing from\n"
2262 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2263 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2264 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2265 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2266 " ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2267 " f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2268 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2269 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2270 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2271 " ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2272 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2273 " gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
2276 "#else // !MODE_WATER\n"
2281 "// 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"
2283 "// fragment shader specific:\n"
2284 "#ifdef FRAGMENT_SHADER\n"
2287 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2290 "#ifdef USEFOGHEIGHTTEXTURE\n"
2291 " float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2292 " fogfrac = fogheightpixel.a;\n"
2293 " return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2295 "# ifdef USEFOGOUTSIDE\n"
2296 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2298 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2300 " return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2305 "#ifdef USEOFFSETMAPPING\n"
2306 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2308 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2309 " // 14 sample relief mapping: linear search and then binary search\n"
2310 " // this basically steps forward a small amount repeatedly until it finds\n"
2311 " // itself inside solid, then jitters forward and back using decreasing\n"
2312 " // amounts to find the impact\n"
2313 " //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2314 " //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2315 " float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2316 " float3 RT = float3(TexCoord, 1);\n"
2317 " OffsetVector *= 0.1;\n"
2318 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2319 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2320 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2321 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2322 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2323 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2324 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2325 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2326 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2327 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
2328 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
2329 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
2330 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
2331 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2334 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2335 " // this basically moves forward the full distance, and then backs up based\n"
2336 " // on height of samples\n"
2337 " //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2338 " //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2339 " float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2340 " TexCoord += OffsetVector;\n"
2341 " OffsetVector *= 0.333;\n"
2342 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2343 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2344 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2345 " return TexCoord;\n"
2348 "#endif // USEOFFSETMAPPING\n"
2350 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2351 "#if defined(USESHADOWMAP2D)\n"
2352 "# ifdef USESHADOWMAPORTHO\n"
2353 "# define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2355 "# ifdef USESHADOWMAPVSDCT\n"
2356 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2358 " float3 adir = abs(dir);\n"
2359 " float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2360 " float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2361 " return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2364 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2366 " float3 adir = abs(dir);\n"
2367 " float ma = adir.z;\n"
2368 " float4 proj = float4(dir, 2.5);\n"
2369 " if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2370 " if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2372 " 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"
2374 " float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2375 " 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"
2380 "#endif // defined(USESHADOWMAP2D)\n"
2382 "# ifdef USESHADOWMAP2D\n"
2383 "#ifdef USESHADOWMAPVSDCT\n"
2384 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2386 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2389 "#ifdef USESHADOWMAPVSDCT\n"
2390 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2392 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2396 "# ifdef USESHADOWSAMPLER\n"
2397 "# ifdef USESHADOWMAPPCF\n"
2398 "# define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r \n"
2399 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2400 " 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"
2402 " f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2405 "# ifdef USESHADOWMAPPCF\n"
2406 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2407 "# ifdef GL_ARB_texture_gather\n"
2408 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2410 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2412 " float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2413 "# if USESHADOWMAPPCF > 1\n"
2414 " float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2415 " float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2416 " float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2417 " float4 group4 = step(shadowmaptc.z, texval(-2.0, 0.0));\n"
2418 " float4 group5 = step(shadowmaptc.z, texval( 0.0, 0.0));\n"
2419 " float4 group6 = step(shadowmaptc.z, texval( 2.0, 0.0));\n"
2420 " float4 group7 = step(shadowmaptc.z, texval(-2.0, 2.0));\n"
2421 " float4 group8 = step(shadowmaptc.z, texval( 0.0, 2.0));\n"
2422 " float4 group9 = step(shadowmaptc.z, texval( 2.0, 2.0));\n"
2423 " float4 locols = float4(group1.ab, group3.ab);\n"
2424 " float4 hicols = float4(group7.rg, group9.rg);\n"
2425 " locols.yz += group2.ab;\n"
2426 " hicols.yz += group8.rg;\n"
2427 " float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2428 " float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2429 " lerp(locols, hicols, offset.y);\n"
2430 " float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2431 " cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2432 " f = dot(cols, float4(1.0/25.0));\n"
2434 " float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2435 " float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2436 " float4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
2437 " float4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
2438 " float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2439 " lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2440 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2443 "# ifdef GL_EXT_gpu_shader4\n"
2444 "# define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2446 "# define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r \n"
2448 "# if USESHADOWMAPPCF > 1\n"
2449 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2450 " center *= ShadowMap_TextureScale;\n"
2451 " 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"
2452 " 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"
2453 " 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"
2454 " 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"
2455 " float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2456 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2458 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2459 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2460 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2461 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2462 " float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2463 " f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2467 " f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2470 "# ifdef USESHADOWMAPORTHO\n"
2471 " return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2477 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2478 "#endif // FRAGMENT_SHADER\n"
2483 "#ifdef MODE_DEFERREDGEOMETRY\n"
2484 "#ifdef VERTEX_SHADER\n"
2487 "float4 gl_Vertex : POSITION,\n"
2488 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2489 "#ifdef USEVERTEXTEXTUREBLEND\n"
2490 "float4 gl_Color : COLOR0,\n"
2492 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2493 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2494 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2495 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2496 "uniform float4x4 TexMatrix : register(c0),\n"
2497 "#ifdef USEVERTEXTEXTUREBLEND\n"
2498 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2500 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2501 "#ifdef USEOFFSETMAPPING\n"
2502 "uniform float3 EyePosition : register(c24),\n"
2504 "out float4 gl_Position : POSITION,\n"
2505 "#ifdef USEVERTEXTEXTUREBLEND\n"
2506 "out float4 gl_FrontColor : COLOR,\n"
2508 "out float4 TexCoordBoth : TEXCOORD0,\n"
2509 "#ifdef USEOFFSETMAPPING\n"
2510 "out float3 EyeVector : TEXCOORD2,\n"
2512 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2513 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2514 "out float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\n"
2517 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2518 "#ifdef USEVERTEXTEXTUREBLEND\n"
2520 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2522 " gl_FrontColor = gl_Color; // Cg is forward\n"
2524 " TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2527 " // transform unnormalized eye direction into tangent space\n"
2528 "#ifdef USEOFFSETMAPPING\n"
2529 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2530 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2531 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2532 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2535 " VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2536 " VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2537 " VectorR.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2538 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2539 " VectorR.w = gl_Position.z;\n"
2541 "#endif // VERTEX_SHADER\n"
2543 "#ifdef FRAGMENT_SHADER\n"
2546 "float4 TexCoordBoth : TEXCOORD0,\n"
2547 "float3 EyeVector : TEXCOORD2,\n"
2548 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2549 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2550 "float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
2551 "uniform sampler Texture_Normal : register(s0),\n"
2552 "#ifdef USEALPHAKILL\n"
2553 "uniform sampler Texture_Color : register(s1),\n"
2555 "uniform sampler Texture_Gloss : register(s2),\n"
2556 "#ifdef USEVERTEXTEXTUREBLEND\n"
2557 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2558 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2560 "#ifdef USEOFFSETMAPPING\n"
2561 "uniform float OffsetMapping_Scale : register(c24),\n"
2563 "uniform half SpecularPower : register(c36),\n"
2565 "out float4 gl_FragData0 : COLOR0,\n"
2566 "out float4 gl_FragData1 : COLOR1\n"
2568 "out float4 gl_FragColor : COLOR\n"
2572 " float2 TexCoord = TexCoordBoth.xy;\n"
2573 "#ifdef USEOFFSETMAPPING\n"
2574 " // apply offsetmapping\n"
2575 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2576 "#define TexCoord TexCoordOffset\n"
2579 "#ifdef USEALPHAKILL\n"
2580 " if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2584 "#ifdef USEVERTEXTEXTUREBLEND\n"
2585 " float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2586 " float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2587 " //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2588 " //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2591 "#ifdef USEVERTEXTEXTUREBLEND\n"
2592 " float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2593 " float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2595 " float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2596 " float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2600 " 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"
2601 " float Depth = VectorR.w / 256.0;\n"
2602 " float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
2603 "// float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
2604 " depthcolor.yz -= floor(depthcolor.yz);\n"
2605 " gl_FragData1 = depthcolor;\n"
2607 " gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2610 "#endif // FRAGMENT_SHADER\n"
2611 "#else // !MODE_DEFERREDGEOMETRY\n"
2616 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2617 "#ifdef VERTEX_SHADER\n"
2620 "float4 gl_Vertex : POSITION,\n"
2621 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2622 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2623 "out float4 gl_Position : POSITION,\n"
2624 "out float4 ModelViewPosition : TEXCOORD0\n"
2627 " ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2628 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2630 "#endif // VERTEX_SHADER\n"
2632 "#ifdef FRAGMENT_SHADER\n"
2636 "float2 Pixel : VPOS,\n"
2638 "float2 Pixel : WPOS,\n"
2640 "float4 ModelViewPosition : TEXCOORD0,\n"
2641 "uniform float4x4 ViewToLight : register(c44),\n"
2642 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2643 "uniform float3 LightPosition : register(c23),\n"
2644 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2645 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2646 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2647 "#ifdef USESPECULAR\n"
2648 "uniform half3 DeferredColor_Specular : register(c11),\n"
2649 "uniform half SpecularPower : register(c36),\n"
2651 "uniform sampler Texture_Attenuation : register(s9),\n"
2652 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2653 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2655 "#ifdef USECUBEFILTER\n"
2656 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2659 "#ifdef USESHADOWMAP2D\n"
2660 "# ifdef USESHADOWSAMPLER\n"
2661 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2663 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2667 "#ifdef USESHADOWMAPVSDCT\n"
2668 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2671 "#if defined(USESHADOWMAP2D)\n"
2672 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2673 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2676 "out float4 gl_FragData0 : COLOR0,\n"
2677 "out float4 gl_FragData1 : COLOR1\n"
2680 " // calculate viewspace pixel position\n"
2681 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2682 " //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2683 " float3 position;\n"
2685 " position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
2687 " position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2689 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2690 " // decode viewspace pixel normal\n"
2691 " half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2692 " half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2693 " // surfacenormal = pixel normal in viewspace\n"
2694 " // LightVector = pixel to light in viewspace\n"
2695 " // CubeVector = position in lightspace\n"
2696 " // eyevector = pixel to view in viewspace\n"
2697 " float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2698 " half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2699 "#ifdef USEDIFFUSE\n"
2700 " // calculate diffuse shading\n"
2701 " half3 lightnormal = half3(normalize(LightPosition - position));\n"
2702 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2704 "#ifdef USESPECULAR\n"
2705 " // calculate directional shading\n"
2706 " float3 eyevector = position * -1.0;\n"
2707 "# ifdef USEEXACTSPECULARMATH\n"
2708 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
2710 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2711 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
2715 "#if defined(USESHADOWMAP2D)\n"
2716 " fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2717 "#ifdef USESHADOWMAPVSDCT\n"
2718 ", Texture_CubeProjection\n"
2723 "#ifdef USEDIFFUSE\n"
2724 " gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2726 " gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2728 "#ifdef USESPECULAR\n"
2729 " gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2731 " gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2734 "# ifdef USECUBEFILTER\n"
2735 " float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2736 " gl_FragData0.rgb *= cubecolor;\n"
2737 " gl_FragData1.rgb *= cubecolor;\n"
2740 "#endif // FRAGMENT_SHADER\n"
2741 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2746 "#ifdef VERTEX_SHADER\n"
2749 "float4 gl_Vertex : POSITION,\n"
2750 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2751 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2752 "float4 gl_Color : COLOR0,\n"
2754 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2755 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2756 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2757 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2758 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2760 "uniform float3 EyePosition : register(c24),\n"
2761 "uniform float4x4 TexMatrix : register(c0),\n"
2762 "#ifdef USEVERTEXTEXTUREBLEND\n"
2763 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2765 "#ifdef MODE_LIGHTSOURCE\n"
2766 "uniform float4x4 ModelToLight : register(c20),\n"
2768 "#ifdef MODE_LIGHTSOURCE\n"
2769 "uniform float3 LightPosition : register(c27),\n"
2771 "#ifdef MODE_LIGHTDIRECTION\n"
2772 "uniform float3 LightDir : register(c26),\n"
2774 "uniform float4 FogPlane : register(c25),\n"
2775 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2776 "uniform float3 LightPosition : register(c27),\n"
2778 "#ifdef USESHADOWMAPORTHO\n"
2779 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2781 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2782 "out float4 gl_FrontColor : COLOR,\n"
2784 "out float4 TexCoordBoth : TEXCOORD0,\n"
2785 "#ifdef USELIGHTMAP\n"
2786 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2788 "#ifdef USEEYEVECTOR\n"
2789 "out float3 EyeVector : TEXCOORD2,\n"
2791 "#ifdef USEREFLECTION\n"
2792 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2795 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2797 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE) || defined(USEDIFFUSE)\n"
2798 "out float3 LightVector : TEXCOORD1,\n"
2800 "#ifdef MODE_LIGHTSOURCE\n"
2801 "out float3 CubeVector : TEXCOORD3,\n"
2803 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2804 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2805 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2806 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2808 "#ifdef USESHADOWMAPORTHO\n"
2809 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2811 "out float4 gl_Position : POSITION\n"
2814 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2816 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2818 " gl_FrontColor = gl_Color; // Cg is forward\n"
2821 " // copy the surface texcoord\n"
2822 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2823 "#ifdef USEVERTEXTEXTUREBLEND\n"
2824 " TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2826 "#ifdef USELIGHTMAP\n"
2827 " TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2830 "#ifdef MODE_LIGHTSOURCE\n"
2831 " // transform vertex position into light attenuation/cubemap space\n"
2832 " // (-1 to +1 across the light box)\n"
2833 " CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2835 "# ifdef USEDIFFUSE\n"
2836 " // transform unnormalized light direction into tangent space\n"
2837 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
2838 " // normalize it per pixel)\n"
2839 " float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2840 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2841 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2842 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2846 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2847 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2848 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2849 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2852 " // transform unnormalized eye direction into tangent space\n"
2853 "#ifdef USEEYEVECTOR\n"
2854 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2855 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2856 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2857 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2861 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2862 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2865 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2866 " VectorS = gl_MultiTexCoord1.xyz;\n"
2867 " VectorT = gl_MultiTexCoord2.xyz;\n"
2868 " VectorR = gl_MultiTexCoord3.xyz;\n"
2871 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2872 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2874 "#ifdef USESHADOWMAPORTHO\n"
2875 " ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2878 "#ifdef USEREFLECTION\n"
2879 " ModelViewProjectionPosition = gl_Position;\n"
2882 "#endif // VERTEX_SHADER\n"
2887 "#ifdef FRAGMENT_SHADER\n"
2890 "#ifdef USEDEFERREDLIGHTMAP\n"
2892 "float2 Pixel : VPOS,\n"
2894 "float2 Pixel : WPOS,\n"
2897 "float4 gl_FrontColor : COLOR,\n"
2898 "float4 TexCoordBoth : TEXCOORD0,\n"
2899 "#ifdef USELIGHTMAP\n"
2900 "float2 TexCoordLightmap : TEXCOORD1,\n"
2902 "#ifdef USEEYEVECTOR\n"
2903 "float3 EyeVector : TEXCOORD2,\n"
2905 "#ifdef USEREFLECTION\n"
2906 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2909 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2911 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2912 "float3 LightVector : TEXCOORD1,\n"
2914 "#ifdef MODE_LIGHTSOURCE\n"
2915 "float3 CubeVector : TEXCOORD3,\n"
2917 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2918 "float4 ModelViewPosition : TEXCOORD0,\n"
2920 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2921 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2922 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2923 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2925 "#ifdef USESHADOWMAPORTHO\n"
2926 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2929 "uniform sampler Texture_Normal : register(s0),\n"
2930 "uniform sampler Texture_Color : register(s1),\n"
2931 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2932 "uniform sampler Texture_Gloss : register(s2),\n"
2935 "uniform sampler Texture_Glow : register(s3),\n"
2937 "#ifdef USEVERTEXTEXTUREBLEND\n"
2938 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2939 "uniform sampler Texture_SecondaryColor : register(s5),\n"
2940 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2941 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2944 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
2947 "#ifdef USECOLORMAPPING\n"
2948 "uniform sampler Texture_Pants : register(s4),\n"
2949 "uniform sampler Texture_Shirt : register(s7),\n"
2952 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
2953 "uniform sampler Texture_FogMask : register(s8),\n"
2955 "#ifdef USELIGHTMAP\n"
2956 "uniform sampler Texture_Lightmap : register(s9),\n"
2958 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2959 "uniform sampler Texture_Deluxemap : register(s10),\n"
2961 "#ifdef USEREFLECTION\n"
2962 "uniform sampler Texture_Reflection : register(s7),\n"
2965 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2966 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2967 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2969 "#ifdef USEDEFERREDLIGHTMAP\n"
2970 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2971 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2972 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
2973 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
2976 "#ifdef USECOLORMAPPING\n"
2977 "uniform half3 Color_Pants : register(c7),\n"
2978 "uniform half3 Color_Shirt : register(c8),\n"
2981 "uniform float3 FogColor : register(c16),\n"
2982 "uniform float FogRangeRecip : register(c20),\n"
2983 "uniform float FogPlaneViewDist : register(c19),\n"
2984 "uniform float FogHeightFade : register(c17),\n"
2987 "#ifdef USEOFFSETMAPPING\n"
2988 "uniform float OffsetMapping_Scale : register(c24),\n"
2991 "#ifdef USEDEFERREDLIGHTMAP\n"
2992 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2993 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
2994 "uniform half3 DeferredMod_Specular : register(c13),\n"
2996 "uniform half3 Color_Ambient : register(c3),\n"
2997 "uniform half3 Color_Diffuse : register(c4),\n"
2998 "uniform half3 Color_Specular : register(c5),\n"
2999 "uniform half SpecularPower : register(c36),\n"
3001 "uniform half3 Color_Glow : register(c6),\n"
3003 "uniform half Alpha : register(c0),\n"
3004 "#ifdef USEREFLECTION\n"
3005 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3006 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3007 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3008 "uniform half4 ReflectColor : register(c26),\n"
3010 "#ifdef USEREFLECTCUBE\n"
3011 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3012 "uniform sampler Texture_ReflectMask : register(s5),\n"
3013 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3015 "#ifdef MODE_LIGHTDIRECTION\n"
3016 "uniform half3 LightColor : register(c21),\n"
3018 "#ifdef MODE_LIGHTSOURCE\n"
3019 "uniform half3 LightColor : register(c21),\n"
3022 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3023 "uniform sampler Texture_Attenuation : register(s9),\n"
3024 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3027 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3029 "#ifdef USESHADOWMAP2D\n"
3030 "# ifdef USESHADOWSAMPLER\n"
3031 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3033 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3037 "#ifdef USESHADOWMAPVSDCT\n"
3038 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3041 "#if defined(USESHADOWMAP2D)\n"
3042 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3043 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3045 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3047 "out float4 gl_FragColor : COLOR\n"
3050 " float2 TexCoord = TexCoordBoth.xy;\n"
3051 "#ifdef USEVERTEXTEXTUREBLEND\n"
3052 " float2 TexCoord2 = TexCoordBoth.zw;\n"
3054 "#ifdef USEOFFSETMAPPING\n"
3055 " // apply offsetmapping\n"
3056 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3057 "#define TexCoord TexCoordOffset\n"
3060 " // combine the diffuse textures (base, pants, shirt)\n"
3061 " half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3062 "#ifdef USEALPHAKILL\n"
3063 " if (color.a < 0.5)\n"
3066 " color.a *= Alpha;\n"
3067 "#ifdef USECOLORMAPPING\n"
3068 " color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3070 "#ifdef USEVERTEXTEXTUREBLEND\n"
3071 " half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3072 " //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3073 " //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3074 " color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3076 " //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3079 " // get the surface normal\n"
3080 "#ifdef USEVERTEXTEXTUREBLEND\n"
3081 " half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3083 " half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3086 " // get the material colors\n"
3087 " half3 diffusetex = color.rgb;\n"
3088 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3089 "# ifdef USEVERTEXTEXTUREBLEND\n"
3090 " half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3092 " half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3096 "#ifdef USEREFLECTCUBE\n"
3097 " float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3098 " float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3099 " float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3100 " diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3106 "#ifdef MODE_LIGHTSOURCE\n"
3107 " // light source\n"
3108 "#ifdef USEDIFFUSE\n"
3109 " half3 lightnormal = half3(normalize(LightVector));\n"
3110 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3111 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3112 "#ifdef USESPECULAR\n"
3113 "#ifdef USEEXACTSPECULARMATH\n"
3114 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3116 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3117 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3119 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3122 " color.rgb = diffusetex * Color_Ambient;\n"
3124 " color.rgb *= LightColor;\n"
3125 " color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3126 "#if defined(USESHADOWMAP2D)\n"
3127 " color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3128 "#ifdef USESHADOWMAPVSDCT\n"
3129 ", Texture_CubeProjection\n"
3134 "# ifdef USECUBEFILTER\n"
3135 " color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3138 "#ifdef USESHADOWMAP2D\n"
3139 "#ifdef USESHADOWMAPVSDCT\n"
3140 "// float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3142 "// float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3144 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3145 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3146 "// color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3147 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3148 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3149 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3150 "// color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3151 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3152 "// color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3153 "// color.r = half(shadowmaptc.z);\n"
3154 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3155 "// color.r = half(shadowmaptc.z);\n"
3157 "// color.rgb = abs(CubeVector);\n"
3159 "// color.rgb = half3(1,1,1);\n"
3160 "#endif // MODE_LIGHTSOURCE\n"
3165 "#ifdef MODE_LIGHTDIRECTION\n"
3167 "#ifdef USEDIFFUSE\n"
3168 " half3 lightnormal = half3(normalize(LightVector));\n"
3170 "#define lightcolor LightColor\n"
3171 "#endif // MODE_LIGHTDIRECTION\n"
3172 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3174 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3175 " half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3176 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3177 " // convert modelspace light vector to tangentspace\n"
3178 " half3 lightnormal;\n"
3179 " lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3180 " lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3181 " lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3182 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3183 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3184 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3185 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3186 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3187 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3188 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3189 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3190 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3191 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3192 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3193 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3195 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3196 " half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3197 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3203 "#ifdef MODE_FAKELIGHT\n"
3205 "half3 lightnormal = half3(normalize(EyeVector));\n"
3206 "half3 lightcolor = half3(1.0);\n"
3207 "#endif // MODE_FAKELIGHT\n"
3212 "#ifdef MODE_LIGHTMAP\n"
3213 " color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3214 "#endif // MODE_LIGHTMAP\n"
3215 "#ifdef MODE_VERTEXCOLOR\n"
3216 " color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3217 "#endif // MODE_VERTEXCOLOR\n"
3218 "#ifdef MODE_FLATCOLOR\n"
3219 " color.rgb = diffusetex * Color_Ambient;\n"
3220 "#endif // MODE_FLATCOLOR\n"
3226 "# ifdef USEDIFFUSE\n"
3227 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3228 "# ifdef USESPECULAR\n"
3229 "# ifdef USEEXACTSPECULARMATH\n"
3230 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3232 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3233 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3235 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3237 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3240 " color.rgb = diffusetex * Color_Ambient;\n"
3244 "#ifdef USESHADOWMAPORTHO\n"
3245 " color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
3248 "#ifdef USEDEFERREDLIGHTMAP\n"
3249 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3250 " color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3251 " color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3252 "// color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
3253 "// color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
3257 "#ifdef USEVERTEXTEXTUREBLEND\n"
3258 " color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3260 " color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3265 " color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3268 " // 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"
3269 "#ifdef USEREFLECTION\n"
3270 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3271 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3272 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3273 " float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3274 " // FIXME temporary hack to detect the case that the reflection\n"
3275 " // gets blackened at edges due to leaving the area that contains actual\n"
3277 " // Remove this 'ack once we have a better way to stop this thing from\n"
3279 " float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3280 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3281 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3282 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3283 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3284 " color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3287 " gl_FragColor = float4(color);\n"
3289 "#endif // FRAGMENT_SHADER\n"
3291 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3292 "#endif // !MODE_DEFERREDGEOMETRY\n"
3293 "#endif // !MODE_WATER\n"
3294 "#endif // !MODE_REFRACTION\n"
3295 "#endif // !MODE_BLOOMBLUR\n"
3296 "#endif // !MODE_GENERIC\n"
3297 "#endif // !MODE_POSTPROCESS\n"
3298 "#endif // !MODE_SHOWDEPTH\n"
3299 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3302 char *glslshaderstring = NULL;
3303 char *cgshaderstring = NULL;
3304 char *hlslshaderstring = NULL;
3306 //=======================================================================================================================================================
3308 typedef struct shaderpermutationinfo_s
3310 const char *pretext;
3313 shaderpermutationinfo_t;
3315 typedef struct shadermodeinfo_s
3317 const char *vertexfilename;
3318 const char *geometryfilename;
3319 const char *fragmentfilename;
3320 const char *pretext;
3325 typedef enum shaderpermutation_e
3327 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3328 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3329 SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3330 SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3331 SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3332 SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3333 SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3334 SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3335 SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3336 SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3337 SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3338 SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3339 SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3340 SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3341 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<14, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3342 SHADERPERMUTATION_REFLECTION = 1<<15, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3343 SHADERPERMUTATION_OFFSETMAPPING = 1<<16, ///< adjust texcoords to roughly simulate a displacement mapped surface
3344 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<17, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3345 SHADERPERMUTATION_SHADOWMAP2D = 1<<18, ///< (lightsource) use shadowmap texture as light filter
3346 SHADERPERMUTATION_SHADOWMAPPCF = 1<<19, ///< (lightsource) use percentage closer filtering on shadowmap test results
3347 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<20, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3348 SHADERPERMUTATION_SHADOWSAMPLER = 1<<21, ///< (lightsource) use hardware shadowmap test
3349 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<22, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3350 SHADERPERMUTATION_SHADOWMAPORTHO = 1<<23, //< (lightsource) use orthographic shadowmap projection
3351 SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3352 SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3353 SHADERPERMUTATION_REFLECTCUBE = 1<<26, ///< fake reflections using global cubemap (not HDRI light probe)
3354 SHADERPERMUTATION_LIMIT = 1<<27, ///< size of permutations array
3355 SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
3357 shaderpermutation_t;
3359 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3360 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3362 {"#define USEDIFFUSE\n", " diffuse"},
3363 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3364 {"#define USEVIEWTINT\n", " viewtint"},
3365 {"#define USECOLORMAPPING\n", " colormapping"},
3366 {"#define USESATURATION\n", " saturation"},
3367 {"#define USEFOGINSIDE\n", " foginside"},
3368 {"#define USEFOGOUTSIDE\n", " fogoutside"},
3369 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3370 {"#define USEGAMMARAMPS\n", " gammaramps"},
3371 {"#define USECUBEFILTER\n", " cubefilter"},
3372 {"#define USEGLOW\n", " glow"},
3373 {"#define USEBLOOM\n", " bloom"},
3374 {"#define USESPECULAR\n", " specular"},
3375 {"#define USEPOSTPROCESSING\n", " postprocessing"},
3376 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3377 {"#define USEREFLECTION\n", " reflection"},
3378 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3379 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3380 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3381 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3382 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3383 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3384 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3385 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3386 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3387 {"#define USEALPHAKILL\n", " alphakill"},
3388 {"#define USEREFLECTCUBE\n", " reflectcube"},
3391 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3392 typedef enum shadermode_e
3394 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3395 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3396 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3397 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3398 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3399 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3400 SHADERMODE_FAKELIGHT, ///< (fakelight) modulate texture by "fake" lighting (no lightmaps, no nothing)
3401 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3402 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3403 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3404 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3405 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3406 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3407 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3408 SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3409 SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3414 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3415 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3417 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3418 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3419 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3420 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3421 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3422 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3423 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3424 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3425 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3426 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3427 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3428 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3429 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3430 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3431 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3432 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3436 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3438 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3439 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3440 {"cg/default.cg", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3441 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3442 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3443 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3444 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FAKELIGHT\n", " fakelight"},
3445 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3446 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3447 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3448 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3449 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3450 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3451 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3452 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3453 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3458 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3460 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3461 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3462 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3463 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3464 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3465 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3466 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3467 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3468 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3469 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3470 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3471 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3472 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3473 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3474 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3478 struct r_glsl_permutation_s;
3479 typedef struct r_glsl_permutation_s
3481 /// hash lookup data
3482 struct r_glsl_permutation_s *hashnext;
3484 unsigned int permutation;
3486 /// indicates if we have tried compiling this permutation already
3488 /// 0 if compilation failed
3490 /// locations of detected uniforms in program object, or -1 if not found
3491 int loc_Texture_First;
3492 int loc_Texture_Second;
3493 int loc_Texture_GammaRamps;
3494 int loc_Texture_Normal;
3495 int loc_Texture_Color;
3496 int loc_Texture_Gloss;
3497 int loc_Texture_Glow;
3498 int loc_Texture_SecondaryNormal;
3499 int loc_Texture_SecondaryColor;
3500 int loc_Texture_SecondaryGloss;
3501 int loc_Texture_SecondaryGlow;
3502 int loc_Texture_Pants;
3503 int loc_Texture_Shirt;
3504 int loc_Texture_FogHeightTexture;
3505 int loc_Texture_FogMask;
3506 int loc_Texture_Lightmap;
3507 int loc_Texture_Deluxemap;
3508 int loc_Texture_Attenuation;
3509 int loc_Texture_Cube;
3510 int loc_Texture_Refraction;
3511 int loc_Texture_Reflection;
3512 int loc_Texture_ShadowMap2D;
3513 int loc_Texture_CubeProjection;
3514 int loc_Texture_ScreenDepth;
3515 int loc_Texture_ScreenNormalMap;
3516 int loc_Texture_ScreenDiffuse;
3517 int loc_Texture_ScreenSpecular;
3518 int loc_Texture_ReflectMask;
3519 int loc_Texture_ReflectCube;
3521 int loc_BloomBlur_Parameters;
3523 int loc_Color_Ambient;
3524 int loc_Color_Diffuse;
3525 int loc_Color_Specular;
3527 int loc_Color_Pants;
3528 int loc_Color_Shirt;
3529 int loc_DeferredColor_Ambient;
3530 int loc_DeferredColor_Diffuse;
3531 int loc_DeferredColor_Specular;
3532 int loc_DeferredMod_Diffuse;
3533 int loc_DeferredMod_Specular;
3534 int loc_DistortScaleRefractReflect;
3535 int loc_EyePosition;
3537 int loc_FogHeightFade;
3539 int loc_FogPlaneViewDist;
3540 int loc_FogRangeRecip;
3543 int loc_LightPosition;
3544 int loc_OffsetMapping_Scale;
3546 int loc_ReflectColor;
3547 int loc_ReflectFactor;
3548 int loc_ReflectOffset;
3549 int loc_RefractColor;
3551 int loc_ScreenCenterRefractReflect;
3552 int loc_ScreenScaleRefractReflect;
3553 int loc_ScreenToDepth;
3554 int loc_ShadowMap_Parameters;
3555 int loc_ShadowMap_TextureScale;
3556 int loc_SpecularPower;
3561 int loc_ViewTintColor;
3562 int loc_ViewToLight;
3563 int loc_ModelToLight;
3565 int loc_BackgroundTexMatrix;
3566 int loc_ModelViewProjectionMatrix;
3567 int loc_ModelViewMatrix;
3568 int loc_PixelToScreenTexCoord;
3569 int loc_ModelToReflectCube;
3570 int loc_ShadowMapMatrix;
3571 int loc_BloomColorSubtract;
3573 r_glsl_permutation_t;
3575 #define SHADERPERMUTATION_HASHSIZE 256
3577 // this called both on R_GLSL_CompileShader and R_HLSL_CacheShader
3578 // this function adds more "#define" to supply static parms, could be used by game-specific code part
3579 int vertstrings_count = 0;
3580 int geomstrings_count = 0;
3581 int fragstrings_count = 0;
3582 const char *vertstrings_list[64+3];
3583 const char *geomstrings_list[64+3];
3584 const char *fragstrings_list[64+3];
3585 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
3587 if (mode == SHADERMODE_POSTPROCESS && (permutation & SHADERPERMUTATION_SATURATION))
3588 if (r_glsl_saturation_redcompensate.integer)
3589 fragstrings_list[fragstrings_count++] = "#define SATURATION_REDCOMPENSATE\n";
3592 /// information about each possible shader permutation
3593 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3594 /// currently selected permutation
3595 r_glsl_permutation_t *r_glsl_permutation;
3596 /// storage for permutations linked in the hash table
3597 memexpandablearray_t r_glsl_permutationarray;
3599 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3601 //unsigned int hashdepth = 0;
3602 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3603 r_glsl_permutation_t *p;
3604 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3606 if (p->mode == mode && p->permutation == permutation)
3608 //if (hashdepth > 10)
3609 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3614 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3616 p->permutation = permutation;
3617 p->hashnext = r_glsl_permutationhash[mode][hashindex];
3618 r_glsl_permutationhash[mode][hashindex] = p;
3619 //if (hashdepth > 10)
3620 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3624 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3627 if (!filename || !filename[0])
3629 if (!strcmp(filename, "glsl/default.glsl"))
3631 if (!glslshaderstring)
3633 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3634 if (glslshaderstring)
3635 Con_DPrintf("Loading shaders from file %s...\n", filename);
3637 glslshaderstring = (char *)builtinshaderstring;
3639 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3640 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3641 return shaderstring;
3643 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3646 if (printfromdisknotice)
3647 Con_DPrintf("from disk %s... ", filename);
3648 return shaderstring;
3650 return shaderstring;
3653 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3656 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3657 char *vertexstring, *geometrystring, *fragmentstring;
3658 char permutationname[256];
3665 permutationname[0] = 0;
3666 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
3667 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3668 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3670 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3672 // the first pretext is which type of shader to compile as
3673 // (later these will all be bound together as a program object)
3674 vertstrings_count = 0;
3675 geomstrings_count = 0;
3676 fragstrings_count = 0;
3677 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3678 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3679 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3681 // the second pretext is the mode (for example a light source)
3682 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3683 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3684 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3685 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3687 // now add all the permutation pretexts
3688 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3690 if (permutation & (1<<i))
3692 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3693 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3694 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3695 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3699 // keep line numbers correct
3700 vertstrings_list[vertstrings_count++] = "\n";
3701 geomstrings_list[geomstrings_count++] = "\n";
3702 fragstrings_list[fragstrings_count++] = "\n";
3707 R_CompileShader_AddStaticParms(mode, permutation);
3709 // now append the shader text itself
3710 vertstrings_list[vertstrings_count++] = vertexstring;
3711 geomstrings_list[geomstrings_count++] = geometrystring;
3712 fragstrings_list[fragstrings_count++] = fragmentstring;
3714 // if any sources were NULL, clear the respective list
3716 vertstrings_count = 0;
3717 if (!geometrystring)
3718 geomstrings_count = 0;
3719 if (!fragmentstring)
3720 fragstrings_count = 0;
3722 // compile the shader program
3723 if (vertstrings_count + geomstrings_count + fragstrings_count)
3724 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3728 qglUseProgramObjectARB(p->program);CHECKGLERROR
3729 // look up all the uniform variable names we care about, so we don't
3730 // have to look them up every time we set them
3732 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
3733 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
3734 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3735 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
3736 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
3737 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3738 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
3739 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3740 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3741 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3742 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3743 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
3744 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3745 p->loc_Texture_FogHeightTexture = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3746 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3747 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3748 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3749 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3750 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
3751 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3752 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3753 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3754 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3755 p->loc_Texture_ScreenDepth = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3756 p->loc_Texture_ScreenNormalMap = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3757 p->loc_Texture_ScreenDiffuse = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3758 p->loc_Texture_ScreenSpecular = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3759 p->loc_Texture_ReflectMask = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3760 p->loc_Texture_ReflectCube = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3761 p->loc_Alpha = qglGetUniformLocationARB(p->program, "Alpha");
3762 p->loc_BloomBlur_Parameters = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3763 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
3764 p->loc_Color_Ambient = qglGetUniformLocationARB(p->program, "Color_Ambient");
3765 p->loc_Color_Diffuse = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3766 p->loc_Color_Specular = qglGetUniformLocationARB(p->program, "Color_Specular");
3767 p->loc_Color_Glow = qglGetUniformLocationARB(p->program, "Color_Glow");
3768 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
3769 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
3770 p->loc_DeferredColor_Ambient = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3771 p->loc_DeferredColor_Diffuse = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3772 p->loc_DeferredColor_Specular = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3773 p->loc_DeferredMod_Diffuse = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3774 p->loc_DeferredMod_Specular = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3775 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3776 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
3777 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
3778 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
3779 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
3780 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3781 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3782 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
3783 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
3784 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
3785 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3786 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
3787 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
3788 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
3789 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
3790 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
3791 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
3792 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3793 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3794 p->loc_ScreenToDepth = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3795 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3796 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3797 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
3798 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
3799 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
3800 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
3801 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
3802 p->loc_ViewTintColor = qglGetUniformLocationARB(p->program, "ViewTintColor");
3803 p->loc_ViewToLight = qglGetUniformLocationARB(p->program, "ViewToLight");
3804 p->loc_ModelToLight = qglGetUniformLocationARB(p->program, "ModelToLight");
3805 p->loc_TexMatrix = qglGetUniformLocationARB(p->program, "TexMatrix");
3806 p->loc_BackgroundTexMatrix = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3807 p->loc_ModelViewMatrix = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3808 p->loc_ModelViewProjectionMatrix = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3809 p->loc_PixelToScreenTexCoord = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3810 p->loc_ModelToReflectCube = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3811 p->loc_ShadowMapMatrix = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3812 p->loc_BloomColorSubtract = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
3813 // initialize the samplers to refer to the texture units we use
3814 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
3815 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
3816 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
3817 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
3818 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
3819 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
3820 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
3821 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3822 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3823 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3824 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
3825 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
3826 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
3827 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3828 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
3829 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
3830 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
3831 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
3832 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
3833 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
3834 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
3835 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
3836 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3837 if (p->loc_Texture_ScreenDepth >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth , GL20TU_SCREENDEPTH);
3838 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3839 if (p->loc_Texture_ScreenDiffuse >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse , GL20TU_SCREENDIFFUSE);
3840 if (p->loc_Texture_ScreenSpecular >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3841 if (p->loc_Texture_ReflectMask >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask , GL20TU_REFLECTMASK);
3842 if (p->loc_Texture_ReflectCube >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube , GL20TU_REFLECTCUBE);
3844 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3847 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
3851 Mem_Free(vertexstring);
3853 Mem_Free(geometrystring);
3855 Mem_Free(fragmentstring);
3858 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3860 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3861 if (r_glsl_permutation != perm)
3863 r_glsl_permutation = perm;
3864 if (!r_glsl_permutation->program)
3866 if (!r_glsl_permutation->compiled)
3867 R_GLSL_CompilePermutation(perm, mode, permutation);
3868 if (!r_glsl_permutation->program)
3870 // remove features until we find a valid permutation
3872 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3874 // reduce i more quickly whenever it would not remove any bits
3875 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3876 if (!(permutation & j))
3879 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3880 if (!r_glsl_permutation->compiled)
3881 R_GLSL_CompilePermutation(perm, mode, permutation);
3882 if (r_glsl_permutation->program)
3885 if (i >= SHADERPERMUTATION_COUNT)
3887 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3888 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3889 qglUseProgramObjectARB(0);CHECKGLERROR
3890 return; // no bit left to clear, entire mode is broken
3895 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3897 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3898 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3899 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3903 #include <Cg/cgGL.h>
3904 struct r_cg_permutation_s;
3905 typedef struct r_cg_permutation_s
3907 /// hash lookup data
3908 struct r_cg_permutation_s *hashnext;
3910 unsigned int permutation;
3912 /// indicates if we have tried compiling this permutation already
3914 /// 0 if compilation failed
3917 /// locations of detected parameters in programs, or NULL if not found
3918 CGparameter vp_EyePosition;
3919 CGparameter vp_FogPlane;
3920 CGparameter vp_LightDir;
3921 CGparameter vp_LightPosition;
3922 CGparameter vp_ModelToLight;
3923 CGparameter vp_TexMatrix;
3924 CGparameter vp_BackgroundTexMatrix;
3925 CGparameter vp_ModelViewProjectionMatrix;
3926 CGparameter vp_ModelViewMatrix;
3927 CGparameter vp_ShadowMapMatrix;
3929 CGparameter fp_Texture_First;
3930 CGparameter fp_Texture_Second;
3931 CGparameter fp_Texture_GammaRamps;
3932 CGparameter fp_Texture_Normal;
3933 CGparameter fp_Texture_Color;
3934 CGparameter fp_Texture_Gloss;
3935 CGparameter fp_Texture_Glow;
3936 CGparameter fp_Texture_SecondaryNormal;
3937 CGparameter fp_Texture_SecondaryColor;
3938 CGparameter fp_Texture_SecondaryGloss;
3939 CGparameter fp_Texture_SecondaryGlow;
3940 CGparameter fp_Texture_Pants;
3941 CGparameter fp_Texture_Shirt;
3942 CGparameter fp_Texture_FogHeightTexture;
3943 CGparameter fp_Texture_FogMask;
3944 CGparameter fp_Texture_Lightmap;
3945 CGparameter fp_Texture_Deluxemap;
3946 CGparameter fp_Texture_Attenuation;
3947 CGparameter fp_Texture_Cube;
3948 CGparameter fp_Texture_Refraction;
3949 CGparameter fp_Texture_Reflection;
3950 CGparameter fp_Texture_ShadowMap2D;
3951 CGparameter fp_Texture_CubeProjection;
3952 CGparameter fp_Texture_ScreenDepth;
3953 CGparameter fp_Texture_ScreenNormalMap;
3954 CGparameter fp_Texture_ScreenDiffuse;
3955 CGparameter fp_Texture_ScreenSpecular;
3956 CGparameter fp_Texture_ReflectMask;
3957 CGparameter fp_Texture_ReflectCube;
3958 CGparameter fp_Alpha;
3959 CGparameter fp_BloomBlur_Parameters;
3960 CGparameter fp_ClientTime;
3961 CGparameter fp_Color_Ambient;
3962 CGparameter fp_Color_Diffuse;
3963 CGparameter fp_Color_Specular;
3964 CGparameter fp_Color_Glow;
3965 CGparameter fp_Color_Pants;
3966 CGparameter fp_Color_Shirt;
3967 CGparameter fp_DeferredColor_Ambient;
3968 CGparameter fp_DeferredColor_Diffuse;
3969 CGparameter fp_DeferredColor_Specular;
3970 CGparameter fp_DeferredMod_Diffuse;
3971 CGparameter fp_DeferredMod_Specular;
3972 CGparameter fp_DistortScaleRefractReflect;
3973 CGparameter fp_EyePosition;
3974 CGparameter fp_FogColor;
3975 CGparameter fp_FogHeightFade;
3976 CGparameter fp_FogPlane;
3977 CGparameter fp_FogPlaneViewDist;
3978 CGparameter fp_FogRangeRecip;
3979 CGparameter fp_LightColor;
3980 CGparameter fp_LightDir;
3981 CGparameter fp_LightPosition;
3982 CGparameter fp_OffsetMapping_Scale;
3983 CGparameter fp_PixelSize;
3984 CGparameter fp_ReflectColor;
3985 CGparameter fp_ReflectFactor;
3986 CGparameter fp_ReflectOffset;
3987 CGparameter fp_RefractColor;
3988 CGparameter fp_Saturation;
3989 CGparameter fp_ScreenCenterRefractReflect;
3990 CGparameter fp_ScreenScaleRefractReflect;
3991 CGparameter fp_ScreenToDepth;
3992 CGparameter fp_ShadowMap_Parameters;
3993 CGparameter fp_ShadowMap_TextureScale;
3994 CGparameter fp_SpecularPower;
3995 CGparameter fp_UserVec1;
3996 CGparameter fp_UserVec2;
3997 CGparameter fp_UserVec3;
3998 CGparameter fp_UserVec4;
3999 CGparameter fp_ViewTintColor;
4000 CGparameter fp_ViewToLight;
4001 CGparameter fp_PixelToScreenTexCoord;
4002 CGparameter fp_ModelToReflectCube;
4003 CGparameter fp_BloomColorSubtract;
4007 /// information about each possible shader permutation
4008 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4009 /// currently selected permutation
4010 r_cg_permutation_t *r_cg_permutation;
4011 /// storage for permutations linked in the hash table
4012 memexpandablearray_t r_cg_permutationarray;
4014 #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));}}
4016 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
4018 //unsigned int hashdepth = 0;
4019 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4020 r_cg_permutation_t *p;
4021 for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4023 if (p->mode == mode && p->permutation == permutation)
4025 //if (hashdepth > 10)
4026 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4031 p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4033 p->permutation = permutation;
4034 p->hashnext = r_cg_permutationhash[mode][hashindex];
4035 r_cg_permutationhash[mode][hashindex] = p;
4036 //if (hashdepth > 10)
4037 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4041 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4044 if (!filename || !filename[0])
4046 if (!strcmp(filename, "cg/default.cg"))
4048 if (!cgshaderstring)
4050 cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4052 Con_DPrintf("Loading shaders from file %s...\n", filename);
4054 cgshaderstring = (char *)builtincgshaderstring;
4056 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4057 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4058 return shaderstring;
4060 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4063 if (printfromdisknotice)
4064 Con_DPrintf("from disk %s... ", filename);
4065 return shaderstring;
4067 return shaderstring;
4070 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4072 // TODO: load or create .fp and .vp shader files
4075 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4078 shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4079 int vertstring_length = 0;
4080 int geomstring_length = 0;
4081 int fragstring_length = 0;
4083 char *vertexstring, *geometrystring, *fragmentstring;
4084 char *vertstring, *geomstring, *fragstring;
4085 char permutationname[256];
4086 char cachename[256];
4087 CGprofile vertexProfile;
4088 CGprofile fragmentProfile;
4096 permutationname[0] = 0;
4098 vertexstring = R_CG_GetText(modeinfo->vertexfilename, true);
4099 geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4100 fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4102 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4103 strlcat(cachename, "cg/", sizeof(cachename));
4105 // the first pretext is which type of shader to compile as
4106 // (later these will all be bound together as a program object)
4107 vertstrings_count = 0;
4108 geomstrings_count = 0;
4109 fragstrings_count = 0;
4110 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4111 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4112 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4114 // the second pretext is the mode (for example a light source)
4115 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4116 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4117 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4118 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4119 strlcat(cachename, modeinfo->name, sizeof(cachename));
4121 // now add all the permutation pretexts
4122 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4124 if (permutation & (1<<i))
4126 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4127 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4128 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4129 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4130 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4134 // keep line numbers correct
4135 vertstrings_list[vertstrings_count++] = "\n";
4136 geomstrings_list[geomstrings_count++] = "\n";
4137 fragstrings_list[fragstrings_count++] = "\n";
4142 R_CompileShader_AddStaticParms(mode, permutation);
4144 // replace spaces in the cachename with _ characters
4145 for (i = 0;cachename[i];i++)
4146 if (cachename[i] == ' ')
4149 // now append the shader text itself
4150 vertstrings_list[vertstrings_count++] = vertexstring;
4151 geomstrings_list[geomstrings_count++] = geometrystring;
4152 fragstrings_list[fragstrings_count++] = fragmentstring;
4154 // if any sources were NULL, clear the respective list
4156 vertstrings_count = 0;
4157 if (!geometrystring)
4158 geomstrings_count = 0;
4159 if (!fragmentstring)
4160 fragstrings_count = 0;
4162 vertstring_length = 0;
4163 for (i = 0;i < vertstrings_count;i++)
4164 vertstring_length += strlen(vertstrings_list[i]);
4165 vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4166 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4167 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4169 geomstring_length = 0;
4170 for (i = 0;i < geomstrings_count;i++)
4171 geomstring_length += strlen(geomstrings_list[i]);
4172 geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4173 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4174 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4176 fragstring_length = 0;
4177 for (i = 0;i < fragstrings_count;i++)
4178 fragstring_length += strlen(fragstrings_list[i]);
4179 fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4180 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4181 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4185 //vertexProfile = CG_PROFILE_ARBVP1;
4186 //fragmentProfile = CG_PROFILE_ARBFP1;
4187 vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4188 fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4189 //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4190 //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4191 //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4194 // try to load the cached shader, or generate one
4195 R_CG_CacheShader(p, cachename, vertstring, fragstring);
4197 // if caching failed, do a dynamic compile for now
4199 if (vertstring[0] && !p->vprogram)
4200 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4202 if (fragstring[0] && !p->fprogram)
4203 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4206 // look up all the uniform variable names we care about, so we don't
4207 // have to look them up every time we set them
4211 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4212 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4213 p->vp_EyePosition = cgGetNamedParameter(p->vprogram, "EyePosition");
4214 p->vp_FogPlane = cgGetNamedParameter(p->vprogram, "FogPlane");
4215 p->vp_LightDir = cgGetNamedParameter(p->vprogram, "LightDir");
4216 p->vp_LightPosition = cgGetNamedParameter(p->vprogram, "LightPosition");
4217 p->vp_ModelToLight = cgGetNamedParameter(p->vprogram, "ModelToLight");
4218 p->vp_TexMatrix = cgGetNamedParameter(p->vprogram, "TexMatrix");
4219 p->vp_BackgroundTexMatrix = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4220 p->vp_ModelViewProjectionMatrix = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4221 p->vp_ModelViewMatrix = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4222 p->vp_ShadowMapMatrix = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4228 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4229 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4230 p->fp_Texture_First = cgGetNamedParameter(p->fprogram, "Texture_First");
4231 p->fp_Texture_Second = cgGetNamedParameter(p->fprogram, "Texture_Second");
4232 p->fp_Texture_GammaRamps = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4233 p->fp_Texture_Normal = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4234 p->fp_Texture_Color = cgGetNamedParameter(p->fprogram, "Texture_Color");
4235 p->fp_Texture_Gloss = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4236 p->fp_Texture_Glow = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4237 p->fp_Texture_SecondaryNormal = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4238 p->fp_Texture_SecondaryColor = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4239 p->fp_Texture_SecondaryGloss = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4240 p->fp_Texture_SecondaryGlow = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4241 p->fp_Texture_Pants = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4242 p->fp_Texture_Shirt = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4243 p->fp_Texture_FogHeightTexture = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4244 p->fp_Texture_FogMask = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4245 p->fp_Texture_Lightmap = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4246 p->fp_Texture_Deluxemap = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4247 p->fp_Texture_Attenuation = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4248 p->fp_Texture_Cube = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4249 p->fp_Texture_Refraction = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4250 p->fp_Texture_Reflection = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4251 p->fp_Texture_ShadowMap2D = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4252 p->fp_Texture_CubeProjection = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4253 p->fp_Texture_ScreenDepth = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4254 p->fp_Texture_ScreenNormalMap = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4255 p->fp_Texture_ScreenDiffuse = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4256 p->fp_Texture_ScreenSpecular = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4257 p->fp_Texture_ReflectMask = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4258 p->fp_Texture_ReflectCube = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4259 p->fp_Alpha = cgGetNamedParameter(p->fprogram, "Alpha");
4260 p->fp_BloomBlur_Parameters = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4261 p->fp_ClientTime = cgGetNamedParameter(p->fprogram, "ClientTime");
4262 p->fp_Color_Ambient = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4263 p->fp_Color_Diffuse = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4264 p->fp_Color_Specular = cgGetNamedParameter(p->fprogram, "Color_Specular");
4265 p->fp_Color_Glow = cgGetNamedParameter(p->fprogram, "Color_Glow");
4266 p->fp_Color_Pants = cgGetNamedParameter(p->fprogram, "Color_Pants");
4267 p->fp_Color_Shirt = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4268 p->fp_DeferredColor_Ambient = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4269 p->fp_DeferredColor_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4270 p->fp_DeferredColor_Specular = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4271 p->fp_DeferredMod_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4272 p->fp_DeferredMod_Specular = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4273 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4274 p->fp_EyePosition = cgGetNamedParameter(p->fprogram, "EyePosition");
4275 p->fp_FogColor = cgGetNamedParameter(p->fprogram, "FogColor");
4276 p->fp_FogHeightFade = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4277 p->fp_FogPlane = cgGetNamedParameter(p->fprogram, "FogPlane");
4278 p->fp_FogPlaneViewDist = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4279 p->fp_FogRangeRecip = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4280 p->fp_LightColor = cgGetNamedParameter(p->fprogram, "LightColor");
4281 p->fp_LightDir = cgGetNamedParameter(p->fprogram, "LightDir");
4282 p->fp_LightPosition = cgGetNamedParameter(p->fprogram, "LightPosition");
4283 p->fp_OffsetMapping_Scale = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4284 p->fp_PixelSize = cgGetNamedParameter(p->fprogram, "PixelSize");
4285 p->fp_ReflectColor = cgGetNamedParameter(p->fprogram, "ReflectColor");
4286 p->fp_ReflectFactor = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4287 p->fp_ReflectOffset = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4288 p->fp_RefractColor = cgGetNamedParameter(p->fprogram, "RefractColor");
4289 p->fp_Saturation = cgGetNamedParameter(p->fprogram, "Saturation");
4290 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4291 p->fp_ScreenScaleRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4292 p->fp_ScreenToDepth = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4293 p->fp_ShadowMap_Parameters = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4294 p->fp_ShadowMap_TextureScale = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4295 p->fp_SpecularPower = cgGetNamedParameter(p->fprogram, "SpecularPower");
4296 p->fp_UserVec1 = cgGetNamedParameter(p->fprogram, "UserVec1");
4297 p->fp_UserVec2 = cgGetNamedParameter(p->fprogram, "UserVec2");
4298 p->fp_UserVec3 = cgGetNamedParameter(p->fprogram, "UserVec3");
4299 p->fp_UserVec4 = cgGetNamedParameter(p->fprogram, "UserVec4");
4300 p->fp_ViewTintColor = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4301 p->fp_ViewToLight = cgGetNamedParameter(p->fprogram, "ViewToLight");
4302 p->fp_PixelToScreenTexCoord = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4303 p->fp_ModelToReflectCube = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4304 p->fp_BloomColorSubtract = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4308 if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4309 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4311 Con_Printf("^1CG shader %s failed! some features may not work properly.\n", permutationname);
4315 Mem_Free(vertstring);
4317 Mem_Free(geomstring);
4319 Mem_Free(fragstring);
4321 Mem_Free(vertexstring);
4323 Mem_Free(geometrystring);
4325 Mem_Free(fragmentstring);
4328 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4330 r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4333 if (r_cg_permutation != perm)
4335 r_cg_permutation = perm;
4336 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4338 if (!r_cg_permutation->compiled)
4339 R_CG_CompilePermutation(perm, mode, permutation);
4340 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4342 // remove features until we find a valid permutation
4344 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4346 // reduce i more quickly whenever it would not remove any bits
4347 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4348 if (!(permutation & j))
4351 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4352 if (!r_cg_permutation->compiled)
4353 R_CG_CompilePermutation(perm, mode, permutation);
4354 if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4357 if (i >= SHADERPERMUTATION_COUNT)
4359 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4360 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4361 return; // no bit left to clear, entire mode is broken
4367 if (r_cg_permutation->vprogram)
4369 cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4370 cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4371 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4375 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4376 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4378 if (r_cg_permutation->fprogram)
4380 cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4381 cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4382 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4386 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4387 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4391 if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4392 if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4393 if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4396 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4398 cgGLSetTextureParameter(param, R_GetTexture(tex));
4399 cgGLEnableTextureParameter(param);
4407 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4408 extern D3DCAPS9 vid_d3d9caps;
4411 struct r_hlsl_permutation_s;
4412 typedef struct r_hlsl_permutation_s
4414 /// hash lookup data
4415 struct r_hlsl_permutation_s *hashnext;
4417 unsigned int permutation;
4419 /// indicates if we have tried compiling this permutation already
4421 /// NULL if compilation failed
4422 IDirect3DVertexShader9 *vertexshader;
4423 IDirect3DPixelShader9 *pixelshader;
4425 r_hlsl_permutation_t;
4427 typedef enum D3DVSREGISTER_e
4429 D3DVSREGISTER_TexMatrix = 0, // float4x4
4430 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4431 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4432 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4433 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4434 D3DVSREGISTER_ModelToLight = 20, // float4x4
4435 D3DVSREGISTER_EyePosition = 24,
4436 D3DVSREGISTER_FogPlane = 25,
4437 D3DVSREGISTER_LightDir = 26,
4438 D3DVSREGISTER_LightPosition = 27,
4442 typedef enum D3DPSREGISTER_e
4444 D3DPSREGISTER_Alpha = 0,
4445 D3DPSREGISTER_BloomBlur_Parameters = 1,
4446 D3DPSREGISTER_ClientTime = 2,
4447 D3DPSREGISTER_Color_Ambient = 3,
4448 D3DPSREGISTER_Color_Diffuse = 4,
4449 D3DPSREGISTER_Color_Specular = 5,
4450 D3DPSREGISTER_Color_Glow = 6,
4451 D3DPSREGISTER_Color_Pants = 7,
4452 D3DPSREGISTER_Color_Shirt = 8,
4453 D3DPSREGISTER_DeferredColor_Ambient = 9,
4454 D3DPSREGISTER_DeferredColor_Diffuse = 10,
4455 D3DPSREGISTER_DeferredColor_Specular = 11,
4456 D3DPSREGISTER_DeferredMod_Diffuse = 12,
4457 D3DPSREGISTER_DeferredMod_Specular = 13,
4458 D3DPSREGISTER_DistortScaleRefractReflect = 14,
4459 D3DPSREGISTER_EyePosition = 15, // unused
4460 D3DPSREGISTER_FogColor = 16,
4461 D3DPSREGISTER_FogHeightFade = 17,
4462 D3DPSREGISTER_FogPlane = 18,
4463 D3DPSREGISTER_FogPlaneViewDist = 19,
4464 D3DPSREGISTER_FogRangeRecip = 20,
4465 D3DPSREGISTER_LightColor = 21,
4466 D3DPSREGISTER_LightDir = 22, // unused
4467 D3DPSREGISTER_LightPosition = 23,
4468 D3DPSREGISTER_OffsetMapping_Scale = 24,
4469 D3DPSREGISTER_PixelSize = 25,
4470 D3DPSREGISTER_ReflectColor = 26,
4471 D3DPSREGISTER_ReflectFactor = 27,
4472 D3DPSREGISTER_ReflectOffset = 28,
4473 D3DPSREGISTER_RefractColor = 29,
4474 D3DPSREGISTER_Saturation = 30,
4475 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4476 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4477 D3DPSREGISTER_ScreenToDepth = 33,
4478 D3DPSREGISTER_ShadowMap_Parameters = 34,
4479 D3DPSREGISTER_ShadowMap_TextureScale = 35,
4480 D3DPSREGISTER_SpecularPower = 36,
4481 D3DPSREGISTER_UserVec1 = 37,
4482 D3DPSREGISTER_UserVec2 = 38,
4483 D3DPSREGISTER_UserVec3 = 39,
4484 D3DPSREGISTER_UserVec4 = 40,
4485 D3DPSREGISTER_ViewTintColor = 41,
4486 D3DPSREGISTER_PixelToScreenTexCoord = 42,
4487 D3DPSREGISTER_BloomColorSubtract = 43,
4488 D3DPSREGISTER_ViewToLight = 44, // float4x4
4489 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4494 /// information about each possible shader permutation
4495 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4496 /// currently selected permutation
4497 r_hlsl_permutation_t *r_hlsl_permutation;
4498 /// storage for permutations linked in the hash table
4499 memexpandablearray_t r_hlsl_permutationarray;
4501 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4503 //unsigned int hashdepth = 0;
4504 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4505 r_hlsl_permutation_t *p;
4506 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4508 if (p->mode == mode && p->permutation == permutation)
4510 //if (hashdepth > 10)
4511 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4516 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4518 p->permutation = permutation;
4519 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4520 r_hlsl_permutationhash[mode][hashindex] = p;
4521 //if (hashdepth > 10)
4522 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4526 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4529 if (!filename || !filename[0])
4531 if (!strcmp(filename, "hlsl/default.hlsl"))
4533 if (!hlslshaderstring)
4535 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4536 if (hlslshaderstring)
4537 Con_DPrintf("Loading shaders from file %s...\n", filename);
4539 hlslshaderstring = (char *)builtincgshaderstring;
4541 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4542 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4543 return shaderstring;
4545 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4548 if (printfromdisknotice)
4549 Con_DPrintf("from disk %s... ", filename);
4550 return shaderstring;
4552 return shaderstring;
4556 //#include <d3dx9shader.h>
4557 //#include <d3dx9mesh.h>
4559 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4561 DWORD *vsbin = NULL;
4562 DWORD *psbin = NULL;
4563 fs_offset_t vsbinsize;
4564 fs_offset_t psbinsize;
4565 // IDirect3DVertexShader9 *vs = NULL;
4566 // IDirect3DPixelShader9 *ps = NULL;
4567 ID3DXBuffer *vslog = NULL;
4568 ID3DXBuffer *vsbuffer = NULL;
4569 ID3DXConstantTable *vsconstanttable = NULL;
4570 ID3DXBuffer *pslog = NULL;
4571 ID3DXBuffer *psbuffer = NULL;
4572 ID3DXConstantTable *psconstanttable = NULL;
4575 char temp[MAX_INPUTLINE];
4576 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4577 qboolean debugshader = gl_paranoid.integer != 0;
4578 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4579 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4582 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4583 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4585 if ((!vsbin && vertstring) || (!psbin && fragstring))
4587 const char* dllnames_d3dx9 [] =
4611 dllhandle_t d3dx9_dll = NULL;
4612 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4613 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4614 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4615 dllfunction_t d3dx9_dllfuncs[] =
4617 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
4618 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
4619 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
4622 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4624 DWORD shaderflags = 0;
4626 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4627 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4628 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4629 if (vertstring && vertstring[0])
4633 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4634 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4635 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4636 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4639 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4642 vsbinsize = vsbuffer->GetBufferSize();
4643 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4644 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4645 vsbuffer->Release();
4649 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4650 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4654 if (fragstring && fragstring[0])
4658 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4659 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4660 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4661 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4664 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4667 psbinsize = psbuffer->GetBufferSize();
4668 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4669 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4670 psbuffer->Release();
4674 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4675 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4679 Sys_UnloadLibrary(&d3dx9_dll);
4682 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4686 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4687 if (FAILED(vsresult))
4688 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4689 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4690 if (FAILED(psresult))
4691 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4693 // free the shader data
4694 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4695 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4698 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4701 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4702 int vertstring_length = 0;
4703 int geomstring_length = 0;
4704 int fragstring_length = 0;
4706 char *vertexstring, *geometrystring, *fragmentstring;
4707 char *vertstring, *geomstring, *fragstring;
4708 char permutationname[256];
4709 char cachename[256];
4714 p->vertexshader = NULL;
4715 p->pixelshader = NULL;
4717 permutationname[0] = 0;
4719 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
4720 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4721 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4723 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4724 strlcat(cachename, "hlsl/", sizeof(cachename));
4726 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4727 vertstrings_count = 0;
4728 geomstrings_count = 0;
4729 fragstrings_count = 0;
4730 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4731 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4732 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4734 // the first pretext is which type of shader to compile as
4735 // (later these will all be bound together as a program object)
4736 vertstrings_count = 0;
4737 geomstrings_count = 0;
4738 fragstrings_count = 0;
4739 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4740 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4741 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4743 // the second pretext is the mode (for example a light source)
4744 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4745 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4746 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4747 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4748 strlcat(cachename, modeinfo->name, sizeof(cachename));
4750 // now add all the permutation pretexts
4751 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4753 if (permutation & (1<<i))
4755 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4756 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4757 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4758 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4759 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4763 // keep line numbers correct
4764 vertstrings_list[vertstrings_count++] = "\n";
4765 geomstrings_list[geomstrings_count++] = "\n";
4766 fragstrings_list[fragstrings_count++] = "\n";
4771 R_CompileShader_AddStaticParms(mode, permutation);
4773 // replace spaces in the cachename with _ characters
4774 for (i = 0;cachename[i];i++)
4775 if (cachename[i] == ' ')
4778 // now append the shader text itself
4779 vertstrings_list[vertstrings_count++] = vertexstring;
4780 geomstrings_list[geomstrings_count++] = geometrystring;
4781 fragstrings_list[fragstrings_count++] = fragmentstring;
4783 // if any sources were NULL, clear the respective list
4785 vertstrings_count = 0;
4786 if (!geometrystring)
4787 geomstrings_count = 0;
4788 if (!fragmentstring)
4789 fragstrings_count = 0;
4791 vertstring_length = 0;
4792 for (i = 0;i < vertstrings_count;i++)
4793 vertstring_length += strlen(vertstrings_list[i]);
4794 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4795 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4796 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4798 geomstring_length = 0;
4799 for (i = 0;i < geomstrings_count;i++)
4800 geomstring_length += strlen(geomstrings_list[i]);
4801 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4802 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4803 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4805 fragstring_length = 0;
4806 for (i = 0;i < fragstrings_count;i++)
4807 fragstring_length += strlen(fragstrings_list[i]);
4808 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4809 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4810 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4812 // try to load the cached shader, or generate one
4813 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4815 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4816 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4818 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
4822 Mem_Free(vertstring);
4824 Mem_Free(geomstring);
4826 Mem_Free(fragstring);
4828 Mem_Free(vertexstring);
4830 Mem_Free(geometrystring);
4832 Mem_Free(fragmentstring);
4835 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4836 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4837 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);}
4838 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);}
4839 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);}
4840 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);}
4842 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4843 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4844 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);}
4845 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);}
4846 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);}
4847 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);}
4849 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4851 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4852 if (r_hlsl_permutation != perm)
4854 r_hlsl_permutation = perm;
4855 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4857 if (!r_hlsl_permutation->compiled)
4858 R_HLSL_CompilePermutation(perm, mode, permutation);
4859 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4861 // remove features until we find a valid permutation
4863 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4865 // reduce i more quickly whenever it would not remove any bits
4866 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4867 if (!(permutation & j))
4870 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4871 if (!r_hlsl_permutation->compiled)
4872 R_HLSL_CompilePermutation(perm, mode, permutation);
4873 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4876 if (i >= SHADERPERMUTATION_COUNT)
4878 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4879 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4880 return; // no bit left to clear, entire mode is broken
4884 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4885 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4887 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4888 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4889 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4893 void R_GLSL_Restart_f(void)
4895 unsigned int i, limit;
4896 if (glslshaderstring && glslshaderstring != builtinshaderstring)
4897 Mem_Free(glslshaderstring);
4898 glslshaderstring = NULL;
4899 if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4900 Mem_Free(cgshaderstring);
4901 cgshaderstring = NULL;
4902 if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
4903 Mem_Free(hlslshaderstring);
4904 hlslshaderstring = NULL;
4905 switch(vid.renderpath)
4907 case RENDERPATH_D3D9:
4910 r_hlsl_permutation_t *p;
4911 r_hlsl_permutation = NULL;
4912 // cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4913 // cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4914 // cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4915 // cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4916 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
4917 for (i = 0;i < limit;i++)
4919 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
4921 if (p->vertexshader)
4922 IDirect3DVertexShader9_Release(p->vertexshader);
4924 IDirect3DPixelShader9_Release(p->pixelshader);
4925 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
4928 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4932 case RENDERPATH_D3D10:
4933 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4935 case RENDERPATH_D3D11:
4936 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4938 case RENDERPATH_GL20:
4940 r_glsl_permutation_t *p;
4941 r_glsl_permutation = NULL;
4942 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4943 for (i = 0;i < limit;i++)
4945 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4947 GL_Backend_FreeProgram(p->program);
4948 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4951 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4954 case RENDERPATH_CGGL:
4957 r_cg_permutation_t *p;
4958 r_cg_permutation = NULL;
4959 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4960 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4961 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4962 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4963 limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4964 for (i = 0;i < limit;i++)
4966 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4969 cgDestroyProgram(p->vprogram);
4971 cgDestroyProgram(p->fprogram);
4972 Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4975 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4979 case RENDERPATH_GL13:
4980 case RENDERPATH_GL11:
4985 void R_GLSL_DumpShader_f(void)
4990 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4993 FS_Print(file, "/* The engine may define the following macros:\n");
4994 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4995 for (i = 0;i < SHADERMODE_COUNT;i++)
4996 FS_Print(file, glslshadermodeinfo[i].pretext);
4997 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4998 FS_Print(file, shaderpermutationinfo[i].pretext);
4999 FS_Print(file, "*/\n");
5000 FS_Print(file, builtinshaderstring);
5002 Con_Printf("glsl/default.glsl written\n");
5005 Con_Printf("failed to write to glsl/default.glsl\n");
5008 file = FS_OpenRealFile("cg/default.cg", "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, cgshadermodeinfo[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("cg/default.cg written\n");
5023 Con_Printf("failed to write to cg/default.cg\n");
5027 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
5030 FS_Print(file, "/* The engine may define the following macros:\n");
5031 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5032 for (i = 0;i < SHADERMODE_COUNT;i++)
5033 FS_Print(file, hlslshadermodeinfo[i].pretext);
5034 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5035 FS_Print(file, shaderpermutationinfo[i].pretext);
5036 FS_Print(file, "*/\n");
5037 FS_Print(file, builtincgshaderstring);
5039 Con_Printf("hlsl/default.hlsl written\n");
5042 Con_Printf("failed to write to hlsl/default.hlsl\n");
5046 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
5049 texturemode = GL_MODULATE;
5050 switch (vid.renderpath)
5052 case RENDERPATH_D3D9:
5054 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))));
5055 R_Mesh_TexBind(GL20TU_FIRST , first );
5056 R_Mesh_TexBind(GL20TU_SECOND, second);
5059 case RENDERPATH_D3D10:
5060 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5062 case RENDERPATH_D3D11:
5063 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5065 case RENDERPATH_GL20:
5066 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))));
5067 R_Mesh_TexBind(GL20TU_FIRST , first );
5068 R_Mesh_TexBind(GL20TU_SECOND, second);
5070 case RENDERPATH_CGGL:
5073 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))));
5074 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
5075 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
5078 case RENDERPATH_GL13:
5079 R_Mesh_TexBind(0, first );
5080 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
5081 R_Mesh_TexBind(1, second);
5083 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
5085 case RENDERPATH_GL11:
5086 R_Mesh_TexBind(0, first );
5091 void R_SetupShader_DepthOrShadow(void)
5093 switch (vid.renderpath)
5095 case RENDERPATH_D3D9:
5097 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5100 case RENDERPATH_D3D10:
5101 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5103 case RENDERPATH_D3D11:
5104 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5106 case RENDERPATH_GL20:
5107 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5109 case RENDERPATH_CGGL:
5111 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5114 case RENDERPATH_GL13:
5115 R_Mesh_TexBind(0, 0);
5116 R_Mesh_TexBind(1, 0);
5118 case RENDERPATH_GL11:
5119 R_Mesh_TexBind(0, 0);
5124 void R_SetupShader_ShowDepth(void)
5126 switch (vid.renderpath)
5128 case RENDERPATH_D3D9:
5130 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5133 case RENDERPATH_D3D10:
5134 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5136 case RENDERPATH_D3D11:
5137 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5139 case RENDERPATH_GL20:
5140 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5142 case RENDERPATH_CGGL:
5144 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5147 case RENDERPATH_GL13:
5149 case RENDERPATH_GL11:
5154 extern qboolean r_shadow_usingdeferredprepass;
5155 extern cvar_t r_shadow_deferred_8bitrange;
5156 extern rtexture_t *r_shadow_attenuationgradienttexture;
5157 extern rtexture_t *r_shadow_attenuation2dtexture;
5158 extern rtexture_t *r_shadow_attenuation3dtexture;
5159 extern qboolean r_shadow_usingshadowmap2d;
5160 extern qboolean r_shadow_usingshadowmaportho;
5161 extern float r_shadow_shadowmap_texturescale[2];
5162 extern float r_shadow_shadowmap_parameters[4];
5163 extern qboolean r_shadow_shadowmapvsdct;
5164 extern qboolean r_shadow_shadowmapsampler;
5165 extern int r_shadow_shadowmappcf;
5166 extern rtexture_t *r_shadow_shadowmap2dtexture;
5167 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5168 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5169 extern matrix4x4_t r_shadow_shadowmapmatrix;
5170 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5171 extern int r_shadow_prepass_width;
5172 extern int r_shadow_prepass_height;
5173 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5174 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5175 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
5176 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5177 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5178 extern cvar_t gl_mesh_separatearrays;
5179 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5181 // a blendfunc allows colormod if:
5182 // a) it can never keep the destination pixel invariant, or
5183 // b) it can keep the destination pixel invariant, and still can do so if colormodded
5184 // this is to prevent unintended side effects from colormod
5187 // IF there is a (s, sa) for which for all (d, da),
5188 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5189 // THEN, for this (s, sa) and all (colormod, d, da):
5190 // s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5191 // OBVIOUSLY, this means that
5192 // s*colormod * src(s*colormod, d, sa, da) = 0
5193 // dst(s*colormod, d, sa, da) = 1
5195 // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5197 // main condition to leave dst color invariant:
5198 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5200 // s * 0 + d * dst(s, d, sa, da) == d
5201 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5202 // => colormod is a problem for GL_SRC_COLOR only
5204 // s + d * dst(s, d, sa, da) == d
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 // src == GL_SRC_COLOR:
5209 // s*s + d * dst(s, d, sa, da) == d
5211 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5212 // => colormod is never problematic for these
5213 // src == GL_ONE_MINUS_SRC_COLOR:
5214 // s*(1-s) + d * dst(s, d, sa, da) == d
5215 // => s == 0 or s == 1
5216 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5217 // => colormod is a problem for GL_SRC_COLOR only
5218 // src == GL_DST_COLOR
5219 // s*d + d * dst(s, d, sa, da) == d
5221 // => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5222 // => colormod is always a problem
5225 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5226 // => colormod is never problematic for these
5227 // => BUT, we do not know s! We must assume it is problematic
5228 // then... except in GL_ONE case, where we know all invariant
5230 // src == GL_ONE_MINUS_DST_COLOR
5231 // s*(1-d) + d * dst(s, d, sa, da) == d
5232 // => s == 0 (1-d is impossible to handle for our desired result)
5233 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5234 // => colormod is never problematic for these
5235 // src == GL_SRC_ALPHA
5236 // s*sa + d * dst(s, d, sa, da) == d
5237 // => s == 0, or sa == 0
5238 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5239 // => colormod breaks in the case GL_SRC_COLOR only
5240 // src == GL_ONE_MINUS_SRC_ALPHA
5241 // s*(1-sa) + d * dst(s, d, sa, da) == d
5242 // => s == 0, or sa == 1
5243 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5244 // => colormod breaks in the case GL_SRC_COLOR only
5245 // src == GL_DST_ALPHA
5246 // s*da + d * dst(s, d, sa, da) == d
5248 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5249 // => colormod is never problematic for these
5254 case GL_ONE_MINUS_SRC_COLOR:
5256 case GL_ONE_MINUS_SRC_ALPHA:
5257 if(dst == GL_SRC_COLOR)
5262 case GL_ONE_MINUS_DST_COLOR:
5264 case GL_ONE_MINUS_DST_ALPHA:
5274 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)
5276 // select a permutation of the lighting shader appropriate to this
5277 // combination of texture, entity, light source, and fogging, only use the
5278 // minimum features necessary to avoid wasting rendering time in the
5279 // fragment shader on features that are not being used
5280 unsigned int permutation = 0;
5281 unsigned int mode = 0;
5282 qboolean allow_colormod;
5283 static float dummy_colormod[3] = {1, 1, 1};
5284 float *colormod = rsurface.colormod;
5286 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5287 if (rsurfacepass == RSURFPASS_BACKGROUND)
5289 // distorted background
5290 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5292 mode = SHADERMODE_WATER;
5293 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5294 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5296 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5298 mode = SHADERMODE_REFRACTION;
5299 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5300 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5304 mode = SHADERMODE_GENERIC;
5305 permutation |= SHADERPERMUTATION_DIFFUSE;
5306 GL_BlendFunc(GL_ONE, GL_ZERO);
5307 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5309 GL_AlphaTest(false);
5311 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5313 if (r_glsl_offsetmapping.integer)
5315 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5316 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5317 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5318 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5319 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5321 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5322 if (r_glsl_offsetmapping_reliefmapping.integer)
5323 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5326 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5327 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5328 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5329 permutation |= SHADERPERMUTATION_ALPHAKILL;
5330 // normalmap (deferred prepass), may use alpha test on diffuse
5331 mode = SHADERMODE_DEFERREDGEOMETRY;
5332 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5333 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5334 GL_AlphaTest(false);
5335 GL_BlendFunc(GL_ONE, GL_ZERO);
5336 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5338 else if (rsurfacepass == RSURFPASS_RTLIGHT)
5340 if (r_glsl_offsetmapping.integer)
5342 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5343 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5344 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5345 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5346 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5348 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5349 if (r_glsl_offsetmapping_reliefmapping.integer)
5350 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5353 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5354 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5356 mode = SHADERMODE_LIGHTSOURCE;
5357 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5358 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5359 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5360 permutation |= SHADERPERMUTATION_CUBEFILTER;
5361 if (diffusescale > 0)
5362 permutation |= SHADERPERMUTATION_DIFFUSE;
5363 if (specularscale > 0)
5365 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5366 if (r_shadow_glossexact.integer)
5367 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5369 if (r_refdef.fogenabled)
5370 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5371 if (rsurface.texture->colormapping)
5372 permutation |= SHADERPERMUTATION_COLORMAPPING;
5373 if (r_shadow_usingshadowmap2d)
5375 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5376 if(r_shadow_shadowmapvsdct)
5377 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5379 if (r_shadow_shadowmapsampler)
5380 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5381 if (r_shadow_shadowmappcf > 1)
5382 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5383 else if (r_shadow_shadowmappcf)
5384 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5386 if (rsurface.texture->reflectmasktexture)
5387 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5388 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5389 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5390 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5392 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5394 if (r_glsl_offsetmapping.integer)
5396 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5397 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5398 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5399 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5400 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5402 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5403 if (r_glsl_offsetmapping_reliefmapping.integer)
5404 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5407 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5408 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5409 // unshaded geometry (fullbright or ambient model lighting)
5410 mode = SHADERMODE_FLATCOLOR;
5411 ambientscale = diffusescale = specularscale = 0;
5412 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5413 permutation |= SHADERPERMUTATION_GLOW;
5414 if (r_refdef.fogenabled)
5415 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5416 if (rsurface.texture->colormapping)
5417 permutation |= SHADERPERMUTATION_COLORMAPPING;
5418 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5420 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5421 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5423 if (r_shadow_shadowmapsampler)
5424 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5425 if (r_shadow_shadowmappcf > 1)
5426 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5427 else if (r_shadow_shadowmappcf)
5428 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5430 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5431 permutation |= SHADERPERMUTATION_REFLECTION;
5432 if (rsurface.texture->reflectmasktexture)
5433 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5434 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5435 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5436 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5438 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5440 if (r_glsl_offsetmapping.integer)
5442 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5443 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5444 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5445 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5446 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5448 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5449 if (r_glsl_offsetmapping_reliefmapping.integer)
5450 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5453 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5454 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5455 // directional model lighting
5456 mode = SHADERMODE_LIGHTDIRECTION;
5457 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5458 permutation |= SHADERPERMUTATION_GLOW;
5459 permutation |= SHADERPERMUTATION_DIFFUSE;
5460 if (specularscale > 0)
5462 permutation |= SHADERPERMUTATION_SPECULAR;
5463 if (r_shadow_glossexact.integer)
5464 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5466 if (r_refdef.fogenabled)
5467 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5468 if (rsurface.texture->colormapping)
5469 permutation |= SHADERPERMUTATION_COLORMAPPING;
5470 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5472 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5473 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5475 if (r_shadow_shadowmapsampler)
5476 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5477 if (r_shadow_shadowmappcf > 1)
5478 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5479 else if (r_shadow_shadowmappcf)
5480 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5482 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5483 permutation |= SHADERPERMUTATION_REFLECTION;
5484 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5485 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5486 if (rsurface.texture->reflectmasktexture)
5487 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5488 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5489 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5490 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5492 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5494 if (r_glsl_offsetmapping.integer)
5496 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5497 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5498 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5499 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5500 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5502 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5503 if (r_glsl_offsetmapping_reliefmapping.integer)
5504 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5507 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5508 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5509 // ambient model lighting
5510 mode = SHADERMODE_LIGHTDIRECTION;
5511 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5512 permutation |= SHADERPERMUTATION_GLOW;
5513 if (r_refdef.fogenabled)
5514 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5515 if (rsurface.texture->colormapping)
5516 permutation |= SHADERPERMUTATION_COLORMAPPING;
5517 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5519 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5520 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5522 if (r_shadow_shadowmapsampler)
5523 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5524 if (r_shadow_shadowmappcf > 1)
5525 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5526 else if (r_shadow_shadowmappcf)
5527 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5529 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5530 permutation |= SHADERPERMUTATION_REFLECTION;
5531 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5532 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5533 if (rsurface.texture->reflectmasktexture)
5534 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5535 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5536 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5537 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5541 if (r_glsl_offsetmapping.integer)
5543 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5544 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5545 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5546 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5547 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5549 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5550 if (r_glsl_offsetmapping_reliefmapping.integer)
5551 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5554 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5555 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5557 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5558 permutation |= SHADERPERMUTATION_GLOW;
5559 if (r_refdef.fogenabled)
5560 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5561 if (rsurface.texture->colormapping)
5562 permutation |= SHADERPERMUTATION_COLORMAPPING;
5563 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5565 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5566 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5568 if (r_shadow_shadowmapsampler)
5569 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5570 if (r_shadow_shadowmappcf > 1)
5571 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5572 else if (r_shadow_shadowmappcf)
5573 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5575 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5576 permutation |= SHADERPERMUTATION_REFLECTION;
5577 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5578 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5579 if (rsurface.texture->reflectmasktexture)
5580 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5581 if (FAKELIGHT_ENABLED)
5583 // fake lightmapping (q1bsp, q3bsp, fullbright map)
5584 mode = SHADERMODE_FAKELIGHT;
5585 permutation |= SHADERPERMUTATION_DIFFUSE;
5586 if (specularscale > 0)
5588 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5589 if (r_shadow_glossexact.integer)
5590 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5593 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5595 // deluxemapping (light direction texture)
5596 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5597 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5599 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5600 permutation |= SHADERPERMUTATION_DIFFUSE;
5601 if (specularscale > 0)
5603 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5604 if (r_shadow_glossexact.integer)
5605 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5608 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5610 // fake deluxemapping (uniform light direction in tangentspace)
5611 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5612 permutation |= SHADERPERMUTATION_DIFFUSE;
5613 if (specularscale > 0)
5615 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5616 if (r_shadow_glossexact.integer)
5617 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5620 else if (rsurface.uselightmaptexture)
5622 // ordinary lightmapping (q1bsp, q3bsp)
5623 mode = SHADERMODE_LIGHTMAP;
5627 // ordinary vertex coloring (q3bsp)
5628 mode = SHADERMODE_VERTEXCOLOR;
5630 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5631 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5632 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5635 colormod = dummy_colormod;
5636 switch(vid.renderpath)
5638 case RENDERPATH_D3D9:
5640 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);
5641 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5642 R_SetupShader_SetPermutationHLSL(mode, permutation);
5643 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5644 if (mode == SHADERMODE_LIGHTSOURCE)
5646 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5647 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5651 if (mode == SHADERMODE_LIGHTDIRECTION)
5653 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5656 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5657 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5658 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5659 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5660 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5662 if (mode == SHADERMODE_LIGHTSOURCE)
5664 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5665 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5666 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5667 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5668 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5670 // additive passes are only darkened by fog, not tinted
5671 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5672 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5676 if (mode == SHADERMODE_FLATCOLOR)
5678 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5680 else if (mode == SHADERMODE_LIGHTDIRECTION)
5682 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]);
5683 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5684 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);
5685 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);
5686 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5687 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5688 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5692 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5693 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5694 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);
5695 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);
5696 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5698 // additive passes are only darkened by fog, not tinted
5699 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5700 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5702 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5703 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);
5704 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5705 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5706 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5707 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5708 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5709 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5710 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5712 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5713 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5714 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5715 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));
5716 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5717 if (rsurface.texture->pantstexture)
5718 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5720 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5721 if (rsurface.texture->shirttexture)
5722 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5724 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5725 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5726 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5727 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5728 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5729 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5730 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5731 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5733 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5734 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5735 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5736 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5737 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5738 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5739 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5740 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5741 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5742 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5743 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5744 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5745 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5746 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5747 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5748 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5749 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5750 if (rsurfacepass == RSURFPASS_BACKGROUND)
5752 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5753 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5754 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5758 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5760 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5761 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5762 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5763 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5764 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5766 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5767 if (rsurface.rtlight)
5769 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5770 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5775 case RENDERPATH_D3D10:
5776 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5778 case RENDERPATH_D3D11:
5779 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5781 case RENDERPATH_GL20:
5782 if (gl_mesh_separatearrays.integer)
5784 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);
5785 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5786 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5787 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5788 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5789 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5790 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5791 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5795 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);
5796 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5798 R_SetupShader_SetPermutationGLSL(mode, permutation);
5799 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5800 if (mode == SHADERMODE_LIGHTSOURCE)
5802 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5803 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5804 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5805 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5806 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5807 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);
5809 // additive passes are only darkened by fog, not tinted
5810 if (r_glsl_permutation->loc_FogColor >= 0)
5811 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5812 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5816 if (mode == SHADERMODE_FLATCOLOR)
5818 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5820 else if (mode == SHADERMODE_LIGHTDIRECTION)
5822 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]);
5823 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]);
5824 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);
5825 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);
5826 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);
5827 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]);
5828 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]);
5832 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]);
5833 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]);
5834 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);
5835 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);
5836 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);
5838 // additive passes are only darkened by fog, not tinted
5839 if (r_glsl_permutation->loc_FogColor >= 0)
5841 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5842 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5844 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5846 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);
5847 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]);
5848 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]);
5849 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]);
5850 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]);
5851 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5852 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5853 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5855 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5856 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5857 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5858 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]);
5859 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]);
5861 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5862 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));
5863 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5864 if (r_glsl_permutation->loc_Color_Pants >= 0)
5866 if (rsurface.texture->pantstexture)
5867 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5869 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5871 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5873 if (rsurface.texture->shirttexture)
5874 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5876 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5878 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]);
5879 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5880 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5881 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5882 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5883 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]);
5884 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5886 // if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_texture_white );
5887 // if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_texture_white );
5888 // if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS , r_texture_gammaramps );
5889 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5890 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5891 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5892 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5893 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5894 if (r_glsl_permutation->loc_Texture_SecondaryColor >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5895 if (r_glsl_permutation->loc_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5896 if (r_glsl_permutation->loc_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5897 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5898 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5899 if (r_glsl_permutation->loc_Texture_ReflectMask >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5900 if (r_glsl_permutation->loc_Texture_ReflectCube >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5901 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5902 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5903 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5904 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5905 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5906 if (rsurfacepass == RSURFPASS_BACKGROUND)
5908 if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5909 else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5910 if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5914 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5916 // if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5917 // if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5918 if (r_glsl_permutation->loc_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5919 if (r_glsl_permutation->loc_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5920 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5922 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture );
5923 if (rsurface.rtlight)
5925 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5926 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5931 case RENDERPATH_CGGL:
5933 if (gl_mesh_separatearrays.integer)
5935 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);
5936 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5937 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5938 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5939 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5940 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5941 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5942 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5946 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);
5947 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5949 R_SetupShader_SetPermutationCG(mode, permutation);
5950 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
5951 if (mode == SHADERMODE_LIGHTSOURCE)
5953 if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
5954 if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5958 if (mode == SHADERMODE_LIGHTDIRECTION)
5960 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
5963 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
5964 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
5965 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
5966 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5967 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
5970 if (mode == SHADERMODE_LIGHTSOURCE)
5972 if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5973 if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
5974 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
5975 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
5976 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
5978 // additive passes are only darkened by fog, not tinted
5979 if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
5980 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5984 if (mode == SHADERMODE_FLATCOLOR)
5986 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
5988 else if (mode == SHADERMODE_LIGHTDIRECTION)
5990 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
5991 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
5992 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
5993 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
5994 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
5995 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
5996 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
6000 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
6001 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
6002 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
6003 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
6004 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
6006 // additive passes are only darkened by fog, not tinted
6007 if (r_cg_permutation->fp_FogColor)
6009 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6010 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
6012 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6015 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
6016 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
6017 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
6018 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
6019 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
6020 if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
6021 if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
6022 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
6024 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
6025 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
6026 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
6027 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
6028 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6029 if (r_cg_permutation->fp_Color_Pants)
6031 if (rsurface.texture->pantstexture)
6032 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6034 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
6037 if (r_cg_permutation->fp_Color_Shirt)
6039 if (rsurface.texture->shirttexture)
6040 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6042 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
6045 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
6046 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
6047 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
6048 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
6049 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
6050 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
6051 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6053 // if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_texture_white );CHECKCGERROR
6054 // if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_texture_white );CHECKCGERROR
6055 // if (r_cg_permutation->fp_Texture_GammaRamps ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps , r_texture_gammaramps );CHECKCGERROR
6056 if (r_cg_permutation->fp_Texture_Normal ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal , rsurface.texture->nmaptexture );CHECKCGERROR
6057 if (r_cg_permutation->fp_Texture_Color ) CG_BindTexture(r_cg_permutation->fp_Texture_Color , rsurface.texture->basetexture );CHECKCGERROR
6058 if (r_cg_permutation->fp_Texture_Gloss ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss , rsurface.texture->glosstexture );CHECKCGERROR
6059 if (r_cg_permutation->fp_Texture_Glow ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow , rsurface.texture->glowtexture );CHECKCGERROR
6060 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture );CHECKCGERROR
6061 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );CHECKCGERROR
6062 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );CHECKCGERROR
6063 if (r_cg_permutation->fp_Texture_SecondaryGlow ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );CHECKCGERROR
6064 if (r_cg_permutation->fp_Texture_Pants ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants , rsurface.texture->pantstexture );CHECKCGERROR
6065 if (r_cg_permutation->fp_Texture_Shirt ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt , rsurface.texture->shirttexture );CHECKCGERROR
6066 if (r_cg_permutation->fp_Texture_ReflectMask ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask , rsurface.texture->reflectmasktexture );CHECKCGERROR
6067 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
6068 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture );CHECKCGERROR
6069 if (r_cg_permutation->fp_Texture_FogMask ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask , r_texture_fogattenuation );CHECKCGERROR
6070 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
6071 if (r_cg_permutation->fp_Texture_Deluxemap ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
6072 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
6073 if (rsurfacepass == RSURFPASS_BACKGROUND)
6075 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
6076 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
6077 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
6081 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
6083 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
6084 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
6085 if (r_cg_permutation->fp_Texture_ScreenDiffuse ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );CHECKCGERROR
6086 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );CHECKCGERROR
6087 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6089 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
6090 if (rsurface.rtlight)
6092 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
6093 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
6100 case RENDERPATH_GL13:
6101 case RENDERPATH_GL11:
6106 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6108 // select a permutation of the lighting shader appropriate to this
6109 // combination of texture, entity, light source, and fogging, only use the
6110 // minimum features necessary to avoid wasting rendering time in the
6111 // fragment shader on features that are not being used
6112 unsigned int permutation = 0;
6113 unsigned int mode = 0;
6114 const float *lightcolorbase = rtlight->currentcolor;
6115 float ambientscale = rtlight->ambientscale;
6116 float diffusescale = rtlight->diffusescale;
6117 float specularscale = rtlight->specularscale;
6118 // this is the location of the light in view space
6119 vec3_t viewlightorigin;
6120 // this transforms from view space (camera) to light space (cubemap)
6121 matrix4x4_t viewtolight;
6122 matrix4x4_t lighttoview;
6123 float viewtolight16f[16];
6124 float range = 1.0f / r_shadow_deferred_8bitrange.value;
6126 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6127 if (rtlight->currentcubemap != r_texture_whitecube)
6128 permutation |= SHADERPERMUTATION_CUBEFILTER;
6129 if (diffusescale > 0)
6130 permutation |= SHADERPERMUTATION_DIFFUSE;
6131 if (specularscale > 0)
6133 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6134 if (r_shadow_glossexact.integer)
6135 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
6137 if (r_shadow_usingshadowmap2d)
6139 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6140 if (r_shadow_shadowmapvsdct)
6141 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6143 if (r_shadow_shadowmapsampler)
6144 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6145 if (r_shadow_shadowmappcf > 1)
6146 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6147 else if (r_shadow_shadowmappcf)
6148 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6150 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6151 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6152 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6153 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6154 switch(vid.renderpath)
6156 case RENDERPATH_D3D9:
6158 R_SetupShader_SetPermutationHLSL(mode, permutation);
6159 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6160 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6161 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
6162 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
6163 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6164 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6165 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6166 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
6167 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6168 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6170 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
6171 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
6172 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
6173 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
6174 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
6175 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
6178 case RENDERPATH_D3D10:
6179 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6181 case RENDERPATH_D3D11:
6182 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6184 case RENDERPATH_GL20:
6185 R_SetupShader_SetPermutationGLSL(mode, permutation);
6186 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6187 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
6188 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);
6189 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);
6190 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);
6191 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]);
6192 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]);
6193 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));
6194 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]);
6195 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6197 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
6198 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
6199 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
6200 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
6201 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
6202 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
6204 case RENDERPATH_CGGL:
6206 R_SetupShader_SetPermutationCG(mode, permutation);
6207 if (r_cg_permutation->fp_LightPosition ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6208 if (r_cg_permutation->fp_ViewToLight ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6209 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
6210 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
6211 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
6212 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
6213 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
6214 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
6215 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
6216 if (r_cg_permutation->fp_PixelToScreenTexCoord ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6218 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
6219 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
6220 if (r_cg_permutation->fp_Texture_ScreenNormalMap ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
6221 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
6222 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
6223 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
6226 case RENDERPATH_GL13:
6227 case RENDERPATH_GL11:
6232 #define SKINFRAME_HASH 1024
6236 int loadsequence; // incremented each level change
6237 memexpandablearray_t array;
6238 skinframe_t *hash[SKINFRAME_HASH];
6241 r_skinframe_t r_skinframe;
6243 void R_SkinFrame_PrepareForPurge(void)
6245 r_skinframe.loadsequence++;
6246 // wrap it without hitting zero
6247 if (r_skinframe.loadsequence >= 200)
6248 r_skinframe.loadsequence = 1;
6251 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6255 // mark the skinframe as used for the purging code
6256 skinframe->loadsequence = r_skinframe.loadsequence;
6259 void R_SkinFrame_Purge(void)
6263 for (i = 0;i < SKINFRAME_HASH;i++)
6265 for (s = r_skinframe.hash[i];s;s = s->next)
6267 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6269 if (s->merged == s->base)
6271 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6272 R_PurgeTexture(s->stain );s->stain = NULL;
6273 R_PurgeTexture(s->merged);s->merged = NULL;
6274 R_PurgeTexture(s->base );s->base = NULL;
6275 R_PurgeTexture(s->pants );s->pants = NULL;
6276 R_PurgeTexture(s->shirt );s->shirt = NULL;
6277 R_PurgeTexture(s->nmap );s->nmap = NULL;
6278 R_PurgeTexture(s->gloss );s->gloss = NULL;
6279 R_PurgeTexture(s->glow );s->glow = NULL;
6280 R_PurgeTexture(s->fog );s->fog = NULL;
6281 R_PurgeTexture(s->reflect);s->reflect = NULL;
6282 s->loadsequence = 0;
6288 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6290 char basename[MAX_QPATH];
6292 Image_StripImageExtension(name, basename, sizeof(basename));
6294 if( last == NULL ) {
6296 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6297 item = r_skinframe.hash[hashindex];
6302 // linearly search through the hash bucket
6303 for( ; item ; item = item->next ) {
6304 if( !strcmp( item->basename, basename ) ) {
6311 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6315 char basename[MAX_QPATH];
6317 Image_StripImageExtension(name, basename, sizeof(basename));
6319 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6320 for (item = r_skinframe.hash[hashindex];item;item = item->next)
6321 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6325 rtexture_t *dyntexture;
6326 // check whether its a dynamic texture
6327 dyntexture = CL_GetDynTexture( basename );
6328 if (!add && !dyntexture)
6330 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6331 memset(item, 0, sizeof(*item));
6332 strlcpy(item->basename, basename, sizeof(item->basename));
6333 item->base = dyntexture; // either NULL or dyntexture handle
6334 item->textureflags = textureflags;
6335 item->comparewidth = comparewidth;
6336 item->compareheight = compareheight;
6337 item->comparecrc = comparecrc;
6338 item->next = r_skinframe.hash[hashindex];
6339 r_skinframe.hash[hashindex] = item;
6341 else if( item->base == NULL )
6343 rtexture_t *dyntexture;
6344 // check whether its a dynamic texture
6345 // 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]
6346 dyntexture = CL_GetDynTexture( basename );
6347 item->base = dyntexture; // either NULL or dyntexture handle
6350 R_SkinFrame_MarkUsed(item);
6354 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6356 unsigned long long avgcolor[5], wsum; \
6364 for(pix = 0; pix < cnt; ++pix) \
6367 for(comp = 0; comp < 3; ++comp) \
6369 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6372 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6374 for(comp = 0; comp < 3; ++comp) \
6375 avgcolor[comp] += getpixel * w; \
6378 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6379 avgcolor[4] += getpixel; \
6381 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6383 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6384 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6385 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6386 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6389 extern cvar_t gl_picmip;
6390 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6393 unsigned char *pixels;
6394 unsigned char *bumppixels;
6395 unsigned char *basepixels = NULL;
6396 int basepixels_width = 0;
6397 int basepixels_height = 0;
6398 skinframe_t *skinframe;
6399 rtexture_t *ddsbase = NULL;
6400 qboolean ddshasalpha = false;
6401 float ddsavgcolor[4];
6402 char basename[MAX_QPATH];
6403 int miplevel = R_PicmipForFlags(textureflags);
6404 int savemiplevel = miplevel;
6407 if (cls.state == ca_dedicated)
6410 // return an existing skinframe if already loaded
6411 // if loading of the first image fails, don't make a new skinframe as it
6412 // would cause all future lookups of this to be missing
6413 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6414 if (skinframe && skinframe->base)
6417 Image_StripImageExtension(name, basename, sizeof(basename));
6419 // check for DDS texture file first
6420 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6422 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6423 if (basepixels == NULL)
6427 // FIXME handle miplevel
6429 if (developer_loading.integer)
6430 Con_Printf("loading skin \"%s\"\n", name);
6432 // we've got some pixels to store, so really allocate this new texture now
6434 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6435 skinframe->stain = NULL;
6436 skinframe->merged = NULL;
6437 skinframe->base = NULL;
6438 skinframe->pants = NULL;
6439 skinframe->shirt = NULL;
6440 skinframe->nmap = NULL;
6441 skinframe->gloss = NULL;
6442 skinframe->glow = NULL;
6443 skinframe->fog = NULL;
6444 skinframe->reflect = NULL;
6445 skinframe->hasalpha = false;
6449 skinframe->base = ddsbase;
6450 skinframe->hasalpha = ddshasalpha;
6451 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6452 if (r_loadfog && skinframe->hasalpha)
6453 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6454 //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]);
6458 basepixels_width = image_width;
6459 basepixels_height = image_height;
6460 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);
6461 if (textureflags & TEXF_ALPHA)
6463 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6465 if (basepixels[j] < 255)
6467 skinframe->hasalpha = true;
6471 if (r_loadfog && skinframe->hasalpha)
6473 // has transparent pixels
6474 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6475 for (j = 0;j < image_width * image_height * 4;j += 4)
6480 pixels[j+3] = basepixels[j+3];
6482 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);
6486 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6487 //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]);
6488 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6489 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6490 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6491 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6496 mymiplevel = savemiplevel;
6497 if (r_loadnormalmap)
6498 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);
6499 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6501 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6502 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6503 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6504 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6507 // _norm is the name used by tenebrae and has been adopted as standard
6508 if (r_loadnormalmap && skinframe->nmap == NULL)
6510 mymiplevel = savemiplevel;
6511 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6513 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);
6517 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6519 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6520 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6521 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);
6523 Mem_Free(bumppixels);
6525 else if (r_shadow_bumpscale_basetexture.value > 0)
6527 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6528 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6529 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);
6532 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6533 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6536 // _luma is supported only for tenebrae compatibility
6537 // _glow is the preferred name
6538 mymiplevel = savemiplevel;
6539 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))))
6541 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);
6542 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6543 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6544 Mem_Free(pixels);pixels = NULL;
6547 mymiplevel = savemiplevel;
6548 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6550 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);
6551 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6552 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6557 mymiplevel = savemiplevel;
6558 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6560 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);
6561 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6562 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6567 mymiplevel = savemiplevel;
6568 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6570 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);
6571 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6572 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6577 mymiplevel = savemiplevel;
6578 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6580 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);
6581 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6582 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6588 Mem_Free(basepixels);
6593 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6594 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6597 unsigned char *temp1, *temp2;
6598 skinframe_t *skinframe;
6600 if (cls.state == ca_dedicated)
6603 // if already loaded just return it, otherwise make a new skinframe
6604 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6605 if (skinframe && skinframe->base)
6608 skinframe->stain = NULL;
6609 skinframe->merged = NULL;
6610 skinframe->base = NULL;
6611 skinframe->pants = NULL;
6612 skinframe->shirt = NULL;
6613 skinframe->nmap = NULL;
6614 skinframe->gloss = NULL;
6615 skinframe->glow = NULL;
6616 skinframe->fog = NULL;
6617 skinframe->reflect = NULL;
6618 skinframe->hasalpha = false;
6620 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6624 if (developer_loading.integer)
6625 Con_Printf("loading 32bit skin \"%s\"\n", name);
6627 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6629 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6630 temp2 = temp1 + width * height * 4;
6631 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6632 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);
6635 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6636 if (textureflags & TEXF_ALPHA)
6638 for (i = 3;i < width * height * 4;i += 4)
6640 if (skindata[i] < 255)
6642 skinframe->hasalpha = true;
6646 if (r_loadfog && skinframe->hasalpha)
6648 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6649 memcpy(fogpixels, skindata, width * height * 4);
6650 for (i = 0;i < width * height * 4;i += 4)
6651 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6652 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6653 Mem_Free(fogpixels);
6657 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6658 //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]);
6663 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6667 skinframe_t *skinframe;
6669 if (cls.state == ca_dedicated)
6672 // if already loaded just return it, otherwise make a new skinframe
6673 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6674 if (skinframe && skinframe->base)
6677 skinframe->stain = NULL;
6678 skinframe->merged = NULL;
6679 skinframe->base = NULL;
6680 skinframe->pants = NULL;
6681 skinframe->shirt = NULL;
6682 skinframe->nmap = NULL;
6683 skinframe->gloss = NULL;
6684 skinframe->glow = NULL;
6685 skinframe->fog = NULL;
6686 skinframe->reflect = NULL;
6687 skinframe->hasalpha = false;
6689 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6693 if (developer_loading.integer)
6694 Con_Printf("loading quake skin \"%s\"\n", name);
6696 // 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)
6697 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height);
6698 memcpy(skinframe->qpixels, skindata, width*height);
6699 skinframe->qwidth = width;
6700 skinframe->qheight = height;
6703 for (i = 0;i < width * height;i++)
6704 featuresmask |= palette_featureflags[skindata[i]];
6706 skinframe->hasalpha = false;
6707 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6708 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6709 skinframe->qgeneratemerged = true;
6710 skinframe->qgeneratebase = skinframe->qhascolormapping;
6711 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6713 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6714 //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]);
6719 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6723 unsigned char *skindata;
6725 if (!skinframe->qpixels)
6728 if (!skinframe->qhascolormapping)
6729 colormapped = false;
6733 if (!skinframe->qgeneratebase)
6738 if (!skinframe->qgeneratemerged)
6742 width = skinframe->qwidth;
6743 height = skinframe->qheight;
6744 skindata = skinframe->qpixels;
6746 if (skinframe->qgeneratenmap)
6748 unsigned char *temp1, *temp2;
6749 skinframe->qgeneratenmap = false;
6750 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6751 temp2 = temp1 + width * height * 4;
6752 // use either a custom palette or the quake palette
6753 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6754 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6755 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);
6759 if (skinframe->qgenerateglow)
6761 skinframe->qgenerateglow = false;
6762 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6767 skinframe->qgeneratebase = false;
6768 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);
6769 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6770 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6774 skinframe->qgeneratemerged = false;
6775 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);
6778 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6780 Mem_Free(skinframe->qpixels);
6781 skinframe->qpixels = NULL;
6785 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)
6788 skinframe_t *skinframe;
6790 if (cls.state == ca_dedicated)
6793 // if already loaded just return it, otherwise make a new skinframe
6794 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6795 if (skinframe && skinframe->base)
6798 skinframe->stain = NULL;
6799 skinframe->merged = NULL;
6800 skinframe->base = NULL;
6801 skinframe->pants = NULL;
6802 skinframe->shirt = NULL;
6803 skinframe->nmap = NULL;
6804 skinframe->gloss = NULL;
6805 skinframe->glow = NULL;
6806 skinframe->fog = NULL;
6807 skinframe->reflect = NULL;
6808 skinframe->hasalpha = false;
6810 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6814 if (developer_loading.integer)
6815 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6817 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6818 if (textureflags & TEXF_ALPHA)
6820 for (i = 0;i < width * height;i++)
6822 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6824 skinframe->hasalpha = true;
6828 if (r_loadfog && skinframe->hasalpha)
6829 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6832 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6833 //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]);
6838 skinframe_t *R_SkinFrame_LoadMissing(void)
6840 skinframe_t *skinframe;
6842 if (cls.state == ca_dedicated)
6845 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6846 skinframe->stain = NULL;
6847 skinframe->merged = NULL;
6848 skinframe->base = NULL;
6849 skinframe->pants = NULL;
6850 skinframe->shirt = NULL;
6851 skinframe->nmap = NULL;
6852 skinframe->gloss = NULL;
6853 skinframe->glow = NULL;
6854 skinframe->fog = NULL;
6855 skinframe->reflect = NULL;
6856 skinframe->hasalpha = false;
6858 skinframe->avgcolor[0] = rand() / RAND_MAX;
6859 skinframe->avgcolor[1] = rand() / RAND_MAX;
6860 skinframe->avgcolor[2] = rand() / RAND_MAX;
6861 skinframe->avgcolor[3] = 1;
6866 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6867 typedef struct suffixinfo_s
6870 qboolean flipx, flipy, flipdiagonal;
6873 static suffixinfo_t suffix[3][6] =
6876 {"px", false, false, false},
6877 {"nx", false, false, false},
6878 {"py", false, false, false},
6879 {"ny", false, false, false},
6880 {"pz", false, false, false},
6881 {"nz", false, false, false}
6884 {"posx", false, false, false},
6885 {"negx", false, false, false},
6886 {"posy", false, false, false},
6887 {"negy", false, false, false},
6888 {"posz", false, false, false},
6889 {"negz", false, false, false}
6892 {"rt", true, false, true},
6893 {"lf", false, true, true},
6894 {"ft", true, true, false},
6895 {"bk", false, false, false},
6896 {"up", true, false, true},
6897 {"dn", true, false, true}
6901 static int componentorder[4] = {0, 1, 2, 3};
6903 rtexture_t *R_LoadCubemap(const char *basename)
6905 int i, j, cubemapsize;
6906 unsigned char *cubemappixels, *image_buffer;
6907 rtexture_t *cubemaptexture;
6909 // must start 0 so the first loadimagepixels has no requested width/height
6911 cubemappixels = NULL;
6912 cubemaptexture = NULL;
6913 // keep trying different suffix groups (posx, px, rt) until one loads
6914 for (j = 0;j < 3 && !cubemappixels;j++)
6916 // load the 6 images in the suffix group
6917 for (i = 0;i < 6;i++)
6919 // generate an image name based on the base and and suffix
6920 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6922 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
6924 // an image loaded, make sure width and height are equal
6925 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6927 // if this is the first image to load successfully, allocate the cubemap memory
6928 if (!cubemappixels && image_width >= 1)
6930 cubemapsize = image_width;
6931 // note this clears to black, so unavailable sides are black
6932 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6934 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6936 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);
6939 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6941 Mem_Free(image_buffer);
6945 // if a cubemap loaded, upload it
6948 if (developer_loading.integer)
6949 Con_Printf("loading cubemap \"%s\"\n", basename);
6951 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6952 Mem_Free(cubemappixels);
6956 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6957 if (developer_loading.integer)
6959 Con_Printf("(tried tried images ");
6960 for (j = 0;j < 3;j++)
6961 for (i = 0;i < 6;i++)
6962 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6963 Con_Print(" and was unable to find any of them).\n");
6966 return cubemaptexture;
6969 rtexture_t *R_GetCubemap(const char *basename)
6972 for (i = 0;i < r_texture_numcubemaps;i++)
6973 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6974 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6975 if (i >= MAX_CUBEMAPS)
6976 return r_texture_whitecube;
6977 r_texture_numcubemaps++;
6978 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6979 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6980 return r_texture_cubemaps[i].texture;
6983 void R_FreeCubemaps(void)
6986 for (i = 0;i < r_texture_numcubemaps;i++)
6988 if (developer_loading.integer)
6989 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6990 if (r_texture_cubemaps[i].texture)
6991 R_FreeTexture(r_texture_cubemaps[i].texture);
6993 r_texture_numcubemaps = 0;
6996 void R_Main_FreeViewCache(void)
6998 if (r_refdef.viewcache.entityvisible)
6999 Mem_Free(r_refdef.viewcache.entityvisible);
7000 if (r_refdef.viewcache.world_pvsbits)
7001 Mem_Free(r_refdef.viewcache.world_pvsbits);
7002 if (r_refdef.viewcache.world_leafvisible)
7003 Mem_Free(r_refdef.viewcache.world_leafvisible);
7004 if (r_refdef.viewcache.world_surfacevisible)
7005 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7006 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
7009 void R_Main_ResizeViewCache(void)
7011 int numentities = r_refdef.scene.numentities;
7012 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
7013 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
7014 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
7015 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
7016 if (r_refdef.viewcache.maxentities < numentities)
7018 r_refdef.viewcache.maxentities = numentities;
7019 if (r_refdef.viewcache.entityvisible)
7020 Mem_Free(r_refdef.viewcache.entityvisible);
7021 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
7023 if (r_refdef.viewcache.world_numclusters != numclusters)
7025 r_refdef.viewcache.world_numclusters = numclusters;
7026 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
7027 if (r_refdef.viewcache.world_pvsbits)
7028 Mem_Free(r_refdef.viewcache.world_pvsbits);
7029 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
7031 if (r_refdef.viewcache.world_numleafs != numleafs)
7033 r_refdef.viewcache.world_numleafs = numleafs;
7034 if (r_refdef.viewcache.world_leafvisible)
7035 Mem_Free(r_refdef.viewcache.world_leafvisible);
7036 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
7038 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
7040 r_refdef.viewcache.world_numsurfaces = numsurfaces;
7041 if (r_refdef.viewcache.world_surfacevisible)
7042 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7043 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
7047 extern rtexture_t *loadingscreentexture;
7048 void gl_main_start(void)
7050 loadingscreentexture = NULL;
7051 r_texture_blanknormalmap = NULL;
7052 r_texture_white = NULL;
7053 r_texture_grey128 = NULL;
7054 r_texture_black = NULL;
7055 r_texture_whitecube = NULL;
7056 r_texture_normalizationcube = NULL;
7057 r_texture_fogattenuation = NULL;
7058 r_texture_fogheighttexture = NULL;
7059 r_texture_gammaramps = NULL;
7060 r_texture_numcubemaps = 0;
7062 r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
7063 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
7065 switch(vid.renderpath)
7067 case RENDERPATH_GL20:
7068 case RENDERPATH_CGGL:
7069 case RENDERPATH_D3D9:
7070 case RENDERPATH_D3D10:
7071 case RENDERPATH_D3D11:
7072 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7073 Cvar_SetValueQuick(&gl_combine, 1);
7074 Cvar_SetValueQuick(&r_glsl, 1);
7075 r_loadnormalmap = true;
7079 case RENDERPATH_GL13:
7080 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7081 Cvar_SetValueQuick(&gl_combine, 1);
7082 Cvar_SetValueQuick(&r_glsl, 0);
7083 r_loadnormalmap = false;
7084 r_loadgloss = false;
7087 case RENDERPATH_GL11:
7088 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7089 Cvar_SetValueQuick(&gl_combine, 0);
7090 Cvar_SetValueQuick(&r_glsl, 0);
7091 r_loadnormalmap = false;
7092 r_loadgloss = false;
7098 R_FrameData_Reset();
7102 memset(r_queries, 0, sizeof(r_queries));
7104 r_qwskincache = NULL;
7105 r_qwskincache_size = 0;
7107 // set up r_skinframe loading system for textures
7108 memset(&r_skinframe, 0, sizeof(r_skinframe));
7109 r_skinframe.loadsequence = 1;
7110 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7112 r_main_texturepool = R_AllocTexturePool();
7113 R_BuildBlankTextures();
7115 if (vid.support.arb_texture_cube_map)
7118 R_BuildNormalizationCube();
7120 r_texture_fogattenuation = NULL;
7121 r_texture_fogheighttexture = NULL;
7122 r_texture_gammaramps = NULL;
7123 //r_texture_fogintensity = NULL;
7124 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7125 memset(&r_waterstate, 0, sizeof(r_waterstate));
7126 r_glsl_permutation = NULL;
7127 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7128 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7129 glslshaderstring = NULL;
7131 r_cg_permutation = NULL;
7132 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7133 Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7134 cgshaderstring = NULL;
7137 r_hlsl_permutation = NULL;
7138 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7139 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7140 hlslshaderstring = NULL;
7142 memset(&r_svbsp, 0, sizeof (r_svbsp));
7144 r_refdef.fogmasktable_density = 0;
7147 void gl_main_shutdown(void)
7150 R_FrameData_Reset();
7152 R_Main_FreeViewCache();
7154 switch(vid.renderpath)
7156 case RENDERPATH_GL11:
7157 case RENDERPATH_GL13:
7158 case RENDERPATH_GL20:
7159 case RENDERPATH_CGGL:
7161 qglDeleteQueriesARB(r_maxqueries, r_queries);
7163 case RENDERPATH_D3D9:
7164 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7166 case RENDERPATH_D3D10:
7167 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7169 case RENDERPATH_D3D11:
7170 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7176 memset(r_queries, 0, sizeof(r_queries));
7178 r_qwskincache = NULL;
7179 r_qwskincache_size = 0;
7181 // clear out the r_skinframe state
7182 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7183 memset(&r_skinframe, 0, sizeof(r_skinframe));
7186 Mem_Free(r_svbsp.nodes);
7187 memset(&r_svbsp, 0, sizeof (r_svbsp));
7188 R_FreeTexturePool(&r_main_texturepool);
7189 loadingscreentexture = NULL;
7190 r_texture_blanknormalmap = NULL;
7191 r_texture_white = NULL;
7192 r_texture_grey128 = NULL;
7193 r_texture_black = NULL;
7194 r_texture_whitecube = NULL;
7195 r_texture_normalizationcube = NULL;
7196 r_texture_fogattenuation = NULL;
7197 r_texture_fogheighttexture = NULL;
7198 r_texture_gammaramps = NULL;
7199 r_texture_numcubemaps = 0;
7200 //r_texture_fogintensity = NULL;
7201 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7202 memset(&r_waterstate, 0, sizeof(r_waterstate));
7206 extern void CL_ParseEntityLump(char *entitystring);
7207 void gl_main_newmap(void)
7209 // FIXME: move this code to client
7210 char *entities, entname[MAX_QPATH];
7212 Mem_Free(r_qwskincache);
7213 r_qwskincache = NULL;
7214 r_qwskincache_size = 0;
7217 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7218 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7220 CL_ParseEntityLump(entities);
7224 if (cl.worldmodel->brush.entities)
7225 CL_ParseEntityLump(cl.worldmodel->brush.entities);
7227 R_Main_FreeViewCache();
7229 R_FrameData_Reset();
7232 void GL_Main_Init(void)
7234 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7236 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7237 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7238 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7239 if (gamemode == GAME_NEHAHRA)
7241 Cvar_RegisterVariable (&gl_fogenable);
7242 Cvar_RegisterVariable (&gl_fogdensity);
7243 Cvar_RegisterVariable (&gl_fogred);
7244 Cvar_RegisterVariable (&gl_foggreen);
7245 Cvar_RegisterVariable (&gl_fogblue);
7246 Cvar_RegisterVariable (&gl_fogstart);
7247 Cvar_RegisterVariable (&gl_fogend);
7248 Cvar_RegisterVariable (&gl_skyclip);
7250 Cvar_RegisterVariable(&r_motionblur);
7251 Cvar_RegisterVariable(&r_motionblur_maxblur);
7252 Cvar_RegisterVariable(&r_motionblur_bmin);
7253 Cvar_RegisterVariable(&r_motionblur_vmin);
7254 Cvar_RegisterVariable(&r_motionblur_vmax);
7255 Cvar_RegisterVariable(&r_motionblur_vcoeff);
7256 Cvar_RegisterVariable(&r_motionblur_randomize);
7257 Cvar_RegisterVariable(&r_damageblur);
7258 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7259 Cvar_RegisterVariable(&r_equalize_entities_minambient);
7260 Cvar_RegisterVariable(&r_equalize_entities_by);
7261 Cvar_RegisterVariable(&r_equalize_entities_to);
7262 Cvar_RegisterVariable(&r_depthfirst);
7263 Cvar_RegisterVariable(&r_useinfinitefarclip);
7264 Cvar_RegisterVariable(&r_farclip_base);
7265 Cvar_RegisterVariable(&r_farclip_world);
7266 Cvar_RegisterVariable(&r_nearclip);
7267 Cvar_RegisterVariable(&r_showbboxes);
7268 Cvar_RegisterVariable(&r_showsurfaces);
7269 Cvar_RegisterVariable(&r_showtris);
7270 Cvar_RegisterVariable(&r_shownormals);
7271 Cvar_RegisterVariable(&r_showlighting);
7272 Cvar_RegisterVariable(&r_showshadowvolumes);
7273 Cvar_RegisterVariable(&r_showcollisionbrushes);
7274 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7275 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7276 Cvar_RegisterVariable(&r_showdisabledepthtest);
7277 Cvar_RegisterVariable(&r_drawportals);
7278 Cvar_RegisterVariable(&r_drawentities);
7279 Cvar_RegisterVariable(&r_draw2d);
7280 Cvar_RegisterVariable(&r_drawworld);
7281 Cvar_RegisterVariable(&r_cullentities_trace);
7282 Cvar_RegisterVariable(&r_cullentities_trace_samples);
7283 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7284 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7285 Cvar_RegisterVariable(&r_cullentities_trace_delay);
7286 Cvar_RegisterVariable(&r_drawviewmodel);
7287 Cvar_RegisterVariable(&r_drawexteriormodel);
7288 Cvar_RegisterVariable(&r_speeds);
7289 Cvar_RegisterVariable(&r_fullbrights);
7290 Cvar_RegisterVariable(&r_wateralpha);
7291 Cvar_RegisterVariable(&r_dynamic);
7292 Cvar_RegisterVariable(&r_fakelight);
7293 Cvar_RegisterVariable(&r_fakelight_intensity);
7294 Cvar_RegisterVariable(&r_fullbright);
7295 Cvar_RegisterVariable(&r_shadows);
7296 Cvar_RegisterVariable(&r_shadows_darken);
7297 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7298 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7299 Cvar_RegisterVariable(&r_shadows_throwdistance);
7300 Cvar_RegisterVariable(&r_shadows_throwdirection);
7301 Cvar_RegisterVariable(&r_shadows_focus);
7302 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7303 Cvar_RegisterVariable(&r_q1bsp_skymasking);
7304 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7305 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7306 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7307 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7308 Cvar_RegisterVariable(&r_fog_exp2);
7309 Cvar_RegisterVariable(&r_drawfog);
7310 Cvar_RegisterVariable(&r_transparentdepthmasking);
7311 Cvar_RegisterVariable(&r_texture_dds_load);
7312 Cvar_RegisterVariable(&r_texture_dds_save);
7313 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7314 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7315 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7316 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7317 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7318 Cvar_RegisterVariable(&r_textureunits);
7319 Cvar_RegisterVariable(&gl_combine);
7320 Cvar_RegisterVariable(&r_glsl);
7321 Cvar_RegisterVariable(&r_glsl_deluxemapping);
7322 Cvar_RegisterVariable(&r_glsl_offsetmapping);
7323 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7324 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7325 Cvar_RegisterVariable(&r_glsl_postprocess);
7326 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7327 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7328 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7329 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7330 Cvar_RegisterVariable(&r_water);
7331 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7332 Cvar_RegisterVariable(&r_water_clippingplanebias);
7333 Cvar_RegisterVariable(&r_water_refractdistort);
7334 Cvar_RegisterVariable(&r_water_reflectdistort);
7335 Cvar_RegisterVariable(&r_water_scissormode);
7336 Cvar_RegisterVariable(&r_lerpsprites);
7337 Cvar_RegisterVariable(&r_lerpmodels);
7338 Cvar_RegisterVariable(&r_lerplightstyles);
7339 Cvar_RegisterVariable(&r_waterscroll);
7340 Cvar_RegisterVariable(&r_bloom);
7341 Cvar_RegisterVariable(&r_bloom_colorscale);
7342 Cvar_RegisterVariable(&r_bloom_brighten);
7343 Cvar_RegisterVariable(&r_bloom_blur);
7344 Cvar_RegisterVariable(&r_bloom_resolution);
7345 Cvar_RegisterVariable(&r_bloom_colorexponent);
7346 Cvar_RegisterVariable(&r_bloom_colorsubtract);
7347 Cvar_RegisterVariable(&r_hdr);
7348 Cvar_RegisterVariable(&r_hdr_scenebrightness);
7349 Cvar_RegisterVariable(&r_hdr_glowintensity);
7350 Cvar_RegisterVariable(&r_hdr_range);
7351 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7352 Cvar_RegisterVariable(&developer_texturelogging);
7353 Cvar_RegisterVariable(&gl_lightmaps);
7354 Cvar_RegisterVariable(&r_test);
7355 Cvar_RegisterVariable(&r_glsl_saturation);
7356 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
7357 Cvar_RegisterVariable(&r_framedatasize);
7358 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7359 Cvar_SetValue("r_fullbrights", 0);
7360 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7362 Cvar_RegisterVariable(&r_track_sprites);
7363 Cvar_RegisterVariable(&r_track_sprites_flags);
7364 Cvar_RegisterVariable(&r_track_sprites_scalew);
7365 Cvar_RegisterVariable(&r_track_sprites_scaleh);
7366 Cvar_RegisterVariable(&r_overheadsprites_perspective);
7367 Cvar_RegisterVariable(&r_overheadsprites_pushback);
7370 extern void R_Textures_Init(void);
7371 extern void GL_Draw_Init(void);
7372 extern void GL_Main_Init(void);
7373 extern void R_Shadow_Init(void);
7374 extern void R_Sky_Init(void);
7375 extern void GL_Surf_Init(void);
7376 extern void R_Particles_Init(void);
7377 extern void R_Explosion_Init(void);
7378 extern void gl_backend_init(void);
7379 extern void Sbar_Init(void);
7380 extern void R_LightningBeams_Init(void);
7381 extern void Mod_RenderInit(void);
7382 extern void Font_Init(void);
7384 void Render_Init(void)
7397 R_LightningBeams_Init();
7406 extern char *ENGINE_EXTENSIONS;
7409 gl_renderer = (const char *)qglGetString(GL_RENDERER);
7410 gl_vendor = (const char *)qglGetString(GL_VENDOR);
7411 gl_version = (const char *)qglGetString(GL_VERSION);
7412 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7416 if (!gl_platformextensions)
7417 gl_platformextensions = "";
7419 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7420 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7421 Con_Printf("GL_VERSION: %s\n", gl_version);
7422 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7423 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7425 VID_CheckExtensions();
7427 // LordHavoc: report supported extensions
7428 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7430 // clear to black (loading plaque will be seen over this)
7431 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7434 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7438 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7440 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7443 p = r_refdef.view.frustum + i;
7448 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7452 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7456 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7460 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7464 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7468 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7472 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7476 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7484 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7488 for (i = 0;i < numplanes;i++)
7495 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7499 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7503 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7507 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7511 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7515 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7519 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7523 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7531 //==================================================================================
7533 // LordHavoc: this stores temporary data used within the same frame
7535 qboolean r_framedata_failed;
7536 static size_t r_framedata_size;
7537 static size_t r_framedata_current;
7538 static void *r_framedata_base;
7540 void R_FrameData_Reset(void)
7542 if (r_framedata_base)
7543 Mem_Free(r_framedata_base);
7544 r_framedata_base = NULL;
7545 r_framedata_size = 0;
7546 r_framedata_current = 0;
7547 r_framedata_failed = false;
7550 void R_FrameData_NewFrame(void)
7553 if (r_framedata_failed)
7554 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
7555 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7556 wantedsize = bound(65536, wantedsize, 128*1024*1024);
7557 if (r_framedata_size != wantedsize)
7559 r_framedata_size = wantedsize;
7560 if (r_framedata_base)
7561 Mem_Free(r_framedata_base);
7562 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
7564 r_framedata_current = 0;
7565 r_framedata_failed = false;
7568 void *R_FrameData_Alloc(size_t size)
7572 // align to 16 byte boundary
7573 size = (size + 15) & ~15;
7574 data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
7575 r_framedata_current += size;
7578 if (r_framedata_current > r_framedata_size)
7579 r_framedata_failed = true;
7581 // return NULL on everything after a failure
7582 if (r_framedata_failed)
7588 void *R_FrameData_Store(size_t size, void *data)
7590 void *d = R_FrameData_Alloc(size);
7592 memcpy(d, data, size);
7596 //==================================================================================
7598 // LordHavoc: animcache originally written by Echon, rewritten since then
7601 * Animation cache prevents re-generating mesh data for an animated model
7602 * multiple times in one frame for lighting, shadowing, reflections, etc.
7605 void R_AnimCache_Free(void)
7609 void R_AnimCache_ClearCache(void)
7612 entity_render_t *ent;
7614 for (i = 0;i < r_refdef.scene.numentities;i++)
7616 ent = r_refdef.scene.entities[i];
7617 ent->animcache_vertex3f = NULL;
7618 ent->animcache_normal3f = NULL;
7619 ent->animcache_svector3f = NULL;
7620 ent->animcache_tvector3f = NULL;
7621 ent->animcache_vertexposition = NULL;
7622 ent->animcache_vertexmesh = NULL;
7623 ent->animcache_vertexpositionbuffer = NULL;
7624 ent->animcache_vertexmeshbuffer = NULL;
7628 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7632 // identical memory layout, so no need to allocate...
7633 // this also provides the vertexposition structure to everything, e.g.
7634 // depth masked rendering currently uses it even if having separate
7636 // NOTE: get rid of this optimization if changing it to e.g. 4f
7637 ent->animcache_vertexposition = (r_vertexposition_t *)ent->animcache_vertex3f;
7640 // get rid of following uses of VERTEXPOSITION, change to the array:
7641 // R_DrawTextureSurfaceList_Sky if skyrendermasked
7642 // R_DrawSurface_TransparentCallback if r_transparentdepthmasking.integer
7643 // R_DrawTextureSurfaceList_DepthOnly
7644 // R_Q1BSP_DrawShadowMap
7646 switch(vid.renderpath)
7648 case RENDERPATH_GL20:
7649 case RENDERPATH_CGGL:
7650 // need the meshbuffers if !gl_mesh_separatearrays.integer
7651 if (gl_mesh_separatearrays.integer)
7654 case RENDERPATH_D3D9:
7655 case RENDERPATH_D3D10:
7656 case RENDERPATH_D3D11:
7657 // always need the meshbuffers
7659 case RENDERPATH_GL13:
7660 case RENDERPATH_GL11:
7661 // never need the meshbuffers
7665 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7666 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7668 if (!ent->animcache_vertexposition)
7669 ent->animcache_vertexposition = (r_vertexposition_t *)R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
7671 if (ent->animcache_vertexposition)
7674 for (i = 0;i < numvertices;i++)
7675 memcpy(ent->animcache_vertexposition[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7677 // TODO: upload vertex buffer?
7679 if (ent->animcache_vertexmesh)
7681 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7682 for (i = 0;i < numvertices;i++)
7683 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7684 if (ent->animcache_svector3f)
7685 for (i = 0;i < numvertices;i++)
7686 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7687 if (ent->animcache_tvector3f)
7688 for (i = 0;i < numvertices;i++)
7689 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7690 if (ent->animcache_normal3f)
7691 for (i = 0;i < numvertices;i++)
7692 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7693 // TODO: upload vertex buffer?
7697 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7699 dp_model_t *model = ent->model;
7701 // see if it's already cached this frame
7702 if (ent->animcache_vertex3f)
7704 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7705 if (wantnormals || wanttangents)
7707 if (ent->animcache_normal3f)
7708 wantnormals = false;
7709 if (ent->animcache_svector3f)
7710 wanttangents = false;
7711 if (wantnormals || wanttangents)
7713 numvertices = model->surfmesh.num_vertices;
7715 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7718 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7719 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7721 if (!r_framedata_failed)
7723 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7724 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7731 // see if this ent is worth caching
7732 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7734 // get some memory for this entity and generate mesh data
7735 numvertices = model->surfmesh.num_vertices;
7736 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7738 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7741 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7742 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7744 if (!r_framedata_failed)
7746 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7747 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7750 return !r_framedata_failed;
7753 void R_AnimCache_CacheVisibleEntities(void)
7756 qboolean wantnormals = true;
7757 qboolean wanttangents = !r_showsurfaces.integer;
7759 switch(vid.renderpath)
7761 case RENDERPATH_GL20:
7762 case RENDERPATH_CGGL:
7763 case RENDERPATH_D3D9:
7764 case RENDERPATH_D3D10:
7765 case RENDERPATH_D3D11:
7767 case RENDERPATH_GL13:
7768 case RENDERPATH_GL11:
7769 wanttangents = false;
7773 if (r_shownormals.integer)
7774 wanttangents = wantnormals = true;
7776 // TODO: thread this
7777 // NOTE: R_PrepareRTLights() also caches entities
7779 for (i = 0;i < r_refdef.scene.numentities;i++)
7780 if (r_refdef.viewcache.entityvisible[i])
7781 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7784 //==================================================================================
7786 static void R_View_UpdateEntityLighting (void)
7789 entity_render_t *ent;
7790 vec3_t tempdiffusenormal, avg;
7791 vec_t f, fa, fd, fdd;
7792 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7794 for (i = 0;i < r_refdef.scene.numentities;i++)
7796 ent = r_refdef.scene.entities[i];
7798 // skip unseen models
7799 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7803 if (ent->model && ent->model->brush.num_leafs)
7805 // TODO: use modellight for r_ambient settings on world?
7806 VectorSet(ent->modellight_ambient, 0, 0, 0);
7807 VectorSet(ent->modellight_diffuse, 0, 0, 0);
7808 VectorSet(ent->modellight_lightdir, 0, 0, 1);
7812 // fetch the lighting from the worldmodel data
7813 VectorClear(ent->modellight_ambient);
7814 VectorClear(ent->modellight_diffuse);
7815 VectorClear(tempdiffusenormal);
7816 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7819 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7820 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7821 if(ent->flags & RENDER_EQUALIZE)
7823 // first fix up ambient lighting...
7824 if(r_equalize_entities_minambient.value > 0)
7826 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7829 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7830 if(fa < r_equalize_entities_minambient.value * fd)
7833 // fa'/fd' = minambient
7834 // fa'+0.25*fd' = fa+0.25*fd
7836 // fa' = fd' * minambient
7837 // fd'*(0.25+minambient) = fa+0.25*fd
7839 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7840 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7842 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7843 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
7844 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7845 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7850 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7852 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
7853 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
7856 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
7857 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
7858 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7864 VectorSet(ent->modellight_ambient, 1, 1, 1);
7866 // move the light direction into modelspace coordinates for lighting code
7867 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7868 if(VectorLength2(ent->modellight_lightdir) == 0)
7869 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7870 VectorNormalize(ent->modellight_lightdir);
7874 #define MAX_LINEOFSIGHTTRACES 64
7876 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7879 vec3_t boxmins, boxmaxs;
7882 dp_model_t *model = r_refdef.scene.worldmodel;
7884 if (!model || !model->brush.TraceLineOfSight)
7887 // expand the box a little
7888 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7889 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7890 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7891 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7892 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7893 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7895 // return true if eye is inside enlarged box
7896 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7900 VectorCopy(eye, start);
7901 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7902 if (model->brush.TraceLineOfSight(model, start, end))
7905 // try various random positions
7906 for (i = 0;i < numsamples;i++)
7908 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7909 if (model->brush.TraceLineOfSight(model, start, end))
7917 static void R_View_UpdateEntityVisible (void)
7922 entity_render_t *ent;
7924 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7925 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7926 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
7927 : RENDER_EXTERIORMODEL;
7928 if (!r_drawviewmodel.integer)
7929 renderimask |= RENDER_VIEWMODEL;
7930 if (!r_drawexteriormodel.integer)
7931 renderimask |= RENDER_EXTERIORMODEL;
7932 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
7934 // worldmodel can check visibility
7935 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
7936 for (i = 0;i < r_refdef.scene.numentities;i++)
7938 ent = r_refdef.scene.entities[i];
7939 if (!(ent->flags & renderimask))
7940 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)))
7941 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))
7942 r_refdef.viewcache.entityvisible[i] = true;
7944 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
7945 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
7947 for (i = 0;i < r_refdef.scene.numentities;i++)
7949 ent = r_refdef.scene.entities[i];
7950 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
7952 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
7954 continue; // temp entities do pvs only
7955 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
7956 ent->last_trace_visibility = realtime;
7957 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
7958 r_refdef.viewcache.entityvisible[i] = 0;
7965 // no worldmodel or it can't check visibility
7966 for (i = 0;i < r_refdef.scene.numentities;i++)
7968 ent = r_refdef.scene.entities[i];
7969 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));
7974 /// only used if skyrendermasked, and normally returns false
7975 int R_DrawBrushModelsSky (void)
7978 entity_render_t *ent;
7981 for (i = 0;i < r_refdef.scene.numentities;i++)
7983 if (!r_refdef.viewcache.entityvisible[i])
7985 ent = r_refdef.scene.entities[i];
7986 if (!ent->model || !ent->model->DrawSky)
7988 ent->model->DrawSky(ent);
7994 static void R_DrawNoModel(entity_render_t *ent);
7995 static void R_DrawModels(void)
7998 entity_render_t *ent;
8000 for (i = 0;i < r_refdef.scene.numentities;i++)
8002 if (!r_refdef.viewcache.entityvisible[i])
8004 ent = r_refdef.scene.entities[i];
8005 r_refdef.stats.entities++;
8006 if (ent->model && ent->model->Draw != NULL)
8007 ent->model->Draw(ent);
8013 static void R_DrawModelsDepth(void)
8016 entity_render_t *ent;
8018 for (i = 0;i < r_refdef.scene.numentities;i++)
8020 if (!r_refdef.viewcache.entityvisible[i])
8022 ent = r_refdef.scene.entities[i];
8023 if (ent->model && ent->model->DrawDepth != NULL)
8024 ent->model->DrawDepth(ent);
8028 static void R_DrawModelsDebug(void)
8031 entity_render_t *ent;
8033 for (i = 0;i < r_refdef.scene.numentities;i++)
8035 if (!r_refdef.viewcache.entityvisible[i])
8037 ent = r_refdef.scene.entities[i];
8038 if (ent->model && ent->model->DrawDebug != NULL)
8039 ent->model->DrawDebug(ent);
8043 static void R_DrawModelsAddWaterPlanes(void)
8046 entity_render_t *ent;
8048 for (i = 0;i < r_refdef.scene.numentities;i++)
8050 if (!r_refdef.viewcache.entityvisible[i])
8052 ent = r_refdef.scene.entities[i];
8053 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
8054 ent->model->DrawAddWaterPlanes(ent);
8058 static void R_View_SetFrustum(const int *scissor)
8061 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
8062 vec3_t forward, left, up, origin, v;
8066 // flipped x coordinates (because x points left here)
8067 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8068 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8070 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
8071 switch(vid.renderpath)
8073 case RENDERPATH_D3D9:
8074 case RENDERPATH_D3D10:
8075 case RENDERPATH_D3D11:
8076 // non-flipped y coordinates
8077 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8078 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8080 case RENDERPATH_GL11:
8081 case RENDERPATH_GL13:
8082 case RENDERPATH_GL20:
8083 case RENDERPATH_CGGL:
8084 // non-flipped y coordinates
8085 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8086 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8091 // we can't trust r_refdef.view.forward and friends in reflected scenes
8092 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
8095 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
8096 r_refdef.view.frustum[0].normal[1] = 0 - 0;
8097 r_refdef.view.frustum[0].normal[2] = -1 - 0;
8098 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
8099 r_refdef.view.frustum[1].normal[1] = 0 + 0;
8100 r_refdef.view.frustum[1].normal[2] = -1 + 0;
8101 r_refdef.view.frustum[2].normal[0] = 0 - 0;
8102 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
8103 r_refdef.view.frustum[2].normal[2] = -1 - 0;
8104 r_refdef.view.frustum[3].normal[0] = 0 + 0;
8105 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
8106 r_refdef.view.frustum[3].normal[2] = -1 + 0;
8110 zNear = r_refdef.nearclip;
8111 nudge = 1.0 - 1.0 / (1<<23);
8112 r_refdef.view.frustum[4].normal[0] = 0 - 0;
8113 r_refdef.view.frustum[4].normal[1] = 0 - 0;
8114 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
8115 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
8116 r_refdef.view.frustum[5].normal[0] = 0 + 0;
8117 r_refdef.view.frustum[5].normal[1] = 0 + 0;
8118 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
8119 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
8125 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8126 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8127 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8128 r_refdef.view.frustum[0].dist = m[15] - m[12];
8130 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8131 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8132 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8133 r_refdef.view.frustum[1].dist = m[15] + m[12];
8135 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8136 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8137 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8138 r_refdef.view.frustum[2].dist = m[15] - m[13];
8140 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8141 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8142 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8143 r_refdef.view.frustum[3].dist = m[15] + m[13];
8145 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8146 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8147 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8148 r_refdef.view.frustum[4].dist = m[15] - m[14];
8150 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8151 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8152 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8153 r_refdef.view.frustum[5].dist = m[15] + m[14];
8156 if (r_refdef.view.useperspective)
8158 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8159 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]);
8160 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]);
8161 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]);
8162 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]);
8164 // then the normals from the corners relative to origin
8165 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
8166 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
8167 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
8168 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
8170 // in a NORMAL view, forward cross left == up
8171 // in a REFLECTED view, forward cross left == down
8172 // so our cross products above need to be adjusted for a left handed coordinate system
8173 CrossProduct(forward, left, v);
8174 if(DotProduct(v, up) < 0)
8176 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
8177 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
8178 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
8179 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
8182 // Leaving those out was a mistake, those were in the old code, and they
8183 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8184 // I couldn't reproduce it after adding those normalizations. --blub
8185 VectorNormalize(r_refdef.view.frustum[0].normal);
8186 VectorNormalize(r_refdef.view.frustum[1].normal);
8187 VectorNormalize(r_refdef.view.frustum[2].normal);
8188 VectorNormalize(r_refdef.view.frustum[3].normal);
8190 // make the corners absolute
8191 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
8192 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
8193 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
8194 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
8197 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8199 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8200 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8201 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8202 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8203 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8207 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8208 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8209 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8210 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8211 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8212 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8213 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8214 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8215 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8216 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8218 r_refdef.view.numfrustumplanes = 5;
8220 if (r_refdef.view.useclipplane)
8222 r_refdef.view.numfrustumplanes = 6;
8223 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8226 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8227 PlaneClassify(r_refdef.view.frustum + i);
8229 // LordHavoc: note to all quake engine coders, Quake had a special case
8230 // for 90 degrees which assumed a square view (wrong), so I removed it,
8231 // Quake2 has it disabled as well.
8233 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8234 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8235 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8236 //PlaneClassify(&frustum[0]);
8238 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8239 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8240 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8241 //PlaneClassify(&frustum[1]);
8243 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8244 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8245 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8246 //PlaneClassify(&frustum[2]);
8248 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8249 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8250 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8251 //PlaneClassify(&frustum[3]);
8254 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8255 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8256 //PlaneClassify(&frustum[4]);
8259 void R_View_UpdateWithScissor(const int *myscissor)
8261 R_Main_ResizeViewCache();
8262 R_View_SetFrustum(myscissor);
8263 R_View_WorldVisibility(r_refdef.view.useclipplane);
8264 R_View_UpdateEntityVisible();
8265 R_View_UpdateEntityLighting();
8268 void R_View_Update(void)
8270 R_Main_ResizeViewCache();
8271 R_View_SetFrustum(NULL);
8272 R_View_WorldVisibility(r_refdef.view.useclipplane);
8273 R_View_UpdateEntityVisible();
8274 R_View_UpdateEntityLighting();
8277 void R_SetupView(qboolean allowwaterclippingplane)
8279 const float *customclipplane = NULL;
8281 if (r_refdef.view.useclipplane && allowwaterclippingplane)
8283 // LordHavoc: couldn't figure out how to make this approach the
8284 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8285 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8286 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8287 dist = r_refdef.view.clipplane.dist;
8288 plane[0] = r_refdef.view.clipplane.normal[0];
8289 plane[1] = r_refdef.view.clipplane.normal[1];
8290 plane[2] = r_refdef.view.clipplane.normal[2];
8292 customclipplane = plane;
8295 if (!r_refdef.view.useperspective)
8296 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);
8297 else if (vid.stencil && r_useinfinitefarclip.integer)
8298 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);
8300 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);
8301 R_SetViewport(&r_refdef.view.viewport);
8304 void R_EntityMatrix(const matrix4x4_t *matrix)
8306 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8308 gl_modelmatrixchanged = false;
8309 gl_modelmatrix = *matrix;
8310 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8311 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8312 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8313 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8315 switch(vid.renderpath)
8317 case RENDERPATH_D3D9:
8319 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8320 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8323 case RENDERPATH_D3D10:
8324 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8326 case RENDERPATH_D3D11:
8327 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8329 case RENDERPATH_GL20:
8330 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8331 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8332 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8334 case RENDERPATH_CGGL:
8337 if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8338 if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8339 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8342 case RENDERPATH_GL13:
8343 case RENDERPATH_GL11:
8344 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8350 void R_ResetViewRendering2D(void)
8352 r_viewport_t viewport;
8355 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8356 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);
8357 R_SetViewport(&viewport);
8358 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8359 GL_Color(1, 1, 1, 1);
8360 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8361 GL_BlendFunc(GL_ONE, GL_ZERO);
8362 GL_AlphaTest(false);
8363 GL_ScissorTest(false);
8364 GL_DepthMask(false);
8365 GL_DepthRange(0, 1);
8366 GL_DepthTest(false);
8367 GL_DepthFunc(GL_LEQUAL);
8368 R_EntityMatrix(&identitymatrix);
8369 R_Mesh_ResetTextureState();
8370 GL_PolygonOffset(0, 0);
8371 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8372 switch(vid.renderpath)
8374 case RENDERPATH_GL11:
8375 case RENDERPATH_GL13:
8376 case RENDERPATH_GL20:
8377 case RENDERPATH_CGGL:
8378 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8380 case RENDERPATH_D3D9:
8381 case RENDERPATH_D3D10:
8382 case RENDERPATH_D3D11:
8385 GL_CullFace(GL_NONE);
8388 void R_ResetViewRendering3D(void)
8393 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8394 GL_Color(1, 1, 1, 1);
8395 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8396 GL_BlendFunc(GL_ONE, GL_ZERO);
8397 GL_AlphaTest(false);
8398 GL_ScissorTest(true);
8400 GL_DepthRange(0, 1);
8402 GL_DepthFunc(GL_LEQUAL);
8403 R_EntityMatrix(&identitymatrix);
8404 R_Mesh_ResetTextureState();
8405 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8406 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8407 switch(vid.renderpath)
8409 case RENDERPATH_GL11:
8410 case RENDERPATH_GL13:
8411 case RENDERPATH_GL20:
8412 case RENDERPATH_CGGL:
8413 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8415 case RENDERPATH_D3D9:
8416 case RENDERPATH_D3D10:
8417 case RENDERPATH_D3D11:
8420 GL_CullFace(r_refdef.view.cullface_back);
8425 R_RenderView_UpdateViewVectors
8428 static void R_RenderView_UpdateViewVectors(void)
8430 // break apart the view matrix into vectors for various purposes
8431 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8432 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8433 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8434 VectorNegate(r_refdef.view.left, r_refdef.view.right);
8435 // make an inverted copy of the view matrix for tracking sprites
8436 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8439 void R_RenderScene(void);
8440 void R_RenderWaterPlanes(void);
8442 static void R_Water_StartFrame(void)
8445 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8446 r_waterstate_waterplane_t *p;
8448 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8451 switch(vid.renderpath)
8453 case RENDERPATH_GL20:
8454 case RENDERPATH_CGGL:
8455 case RENDERPATH_D3D9:
8456 case RENDERPATH_D3D10:
8457 case RENDERPATH_D3D11:
8459 case RENDERPATH_GL13:
8460 case RENDERPATH_GL11:
8464 // set waterwidth and waterheight to the water resolution that will be
8465 // used (often less than the screen resolution for faster rendering)
8466 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8467 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8469 // calculate desired texture sizes
8470 // can't use water if the card does not support the texture size
8471 if (!r_water.integer || r_showsurfaces.integer)
8472 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8473 else if (vid.support.arb_texture_non_power_of_two)
8475 texturewidth = waterwidth;
8476 textureheight = waterheight;
8477 camerawidth = waterwidth;
8478 cameraheight = waterheight;
8482 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
8483 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
8484 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
8485 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
8488 // allocate textures as needed
8489 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8491 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8492 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8494 if (p->texture_refraction)
8495 R_FreeTexture(p->texture_refraction);
8496 p->texture_refraction = NULL;
8497 if (p->texture_reflection)
8498 R_FreeTexture(p->texture_reflection);
8499 p->texture_reflection = NULL;
8500 if (p->texture_camera)
8501 R_FreeTexture(p->texture_camera);
8502 p->texture_camera = NULL;
8504 memset(&r_waterstate, 0, sizeof(r_waterstate));
8505 r_waterstate.texturewidth = texturewidth;
8506 r_waterstate.textureheight = textureheight;
8507 r_waterstate.camerawidth = camerawidth;
8508 r_waterstate.cameraheight = cameraheight;
8511 if (r_waterstate.texturewidth)
8513 r_waterstate.enabled = true;
8515 // when doing a reduced render (HDR) we want to use a smaller area
8516 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8517 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8519 // set up variables that will be used in shader setup
8520 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8521 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8522 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8523 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8526 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8527 r_waterstate.numwaterplanes = 0;
8530 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8532 int triangleindex, planeindex;
8538 r_waterstate_waterplane_t *p;
8539 texture_t *t = R_GetCurrentTexture(surface->texture);
8541 // just use the first triangle with a valid normal for any decisions
8542 VectorClear(normal);
8543 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8545 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8546 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8547 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8548 TriangleNormal(vert[0], vert[1], vert[2], normal);
8549 if (VectorLength2(normal) >= 0.001)
8553 VectorCopy(normal, plane.normal);
8554 VectorNormalize(plane.normal);
8555 plane.dist = DotProduct(vert[0], plane.normal);
8556 PlaneClassify(&plane);
8557 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8559 // skip backfaces (except if nocullface is set)
8560 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8562 VectorNegate(plane.normal, plane.normal);
8564 PlaneClassify(&plane);
8568 // find a matching plane if there is one
8569 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8570 if(p->camera_entity == t->camera_entity)
8571 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8573 if (planeindex >= r_waterstate.maxwaterplanes)
8574 return; // nothing we can do, out of planes
8576 // if this triangle does not fit any known plane rendered this frame, add one
8577 if (planeindex >= r_waterstate.numwaterplanes)
8579 // store the new plane
8580 r_waterstate.numwaterplanes++;
8582 // clear materialflags and pvs
8583 p->materialflags = 0;
8584 p->pvsvalid = false;
8585 p->camera_entity = t->camera_entity;
8586 VectorCopy(surface->mins, p->mins);
8587 VectorCopy(surface->maxs, p->maxs);
8592 p->mins[0] = min(p->mins[0], surface->mins[0]);
8593 p->mins[1] = min(p->mins[1], surface->mins[1]);
8594 p->mins[2] = min(p->mins[2], surface->mins[2]);
8595 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8596 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8597 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8599 // merge this surface's materialflags into the waterplane
8600 p->materialflags |= t->currentmaterialflags;
8601 if(!(p->materialflags & MATERIALFLAG_CAMERA))
8603 // merge this surface's PVS into the waterplane
8604 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8605 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8606 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8608 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8614 static void R_Water_ProcessPlanes(void)
8617 r_refdef_view_t originalview;
8618 r_refdef_view_t myview;
8620 r_waterstate_waterplane_t *p;
8623 originalview = r_refdef.view;
8625 // make sure enough textures are allocated
8626 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8628 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8630 if (!p->texture_refraction)
8631 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);
8632 if (!p->texture_refraction)
8635 else if (p->materialflags & MATERIALFLAG_CAMERA)
8637 if (!p->texture_camera)
8638 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);
8639 if (!p->texture_camera)
8643 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8645 if (!p->texture_reflection)
8646 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);
8647 if (!p->texture_reflection)
8653 r_refdef.view = originalview;
8654 r_refdef.view.showdebug = false;
8655 r_refdef.view.width = r_waterstate.waterwidth;
8656 r_refdef.view.height = r_waterstate.waterheight;
8657 r_refdef.view.useclipplane = true;
8658 myview = r_refdef.view;
8659 r_waterstate.renderingscene = true;
8660 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8662 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8664 r_refdef.view = myview;
8665 if(r_water_scissormode.integer)
8668 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8669 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8672 // render reflected scene and copy into texture
8673 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8674 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8675 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8676 r_refdef.view.clipplane = p->plane;
8678 // reverse the cullface settings for this render
8679 r_refdef.view.cullface_front = GL_FRONT;
8680 r_refdef.view.cullface_back = GL_BACK;
8681 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8683 r_refdef.view.usecustompvs = true;
8685 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8687 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8690 R_ResetViewRendering3D();
8691 R_ClearScreen(r_refdef.fogenabled);
8692 if(r_water_scissormode.integer & 2)
8693 R_View_UpdateWithScissor(myscissor);
8696 if(r_water_scissormode.integer & 1)
8697 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8700 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);
8703 // render the normal view scene and copy into texture
8704 // (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)
8705 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8707 r_refdef.view = myview;
8708 if(r_water_scissormode.integer)
8711 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8712 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8715 r_waterstate.renderingrefraction = true;
8717 r_refdef.view.clipplane = p->plane;
8718 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8719 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8721 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8723 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8724 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8725 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8726 R_RenderView_UpdateViewVectors();
8727 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8729 r_refdef.view.usecustompvs = true;
8730 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);
8734 PlaneClassify(&r_refdef.view.clipplane);
8736 R_ResetViewRendering3D();
8737 R_ClearScreen(r_refdef.fogenabled);
8738 if(r_water_scissormode.integer & 2)
8739 R_View_UpdateWithScissor(myscissor);
8742 if(r_water_scissormode.integer & 1)
8743 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8746 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);
8747 r_waterstate.renderingrefraction = false;
8749 else if (p->materialflags & MATERIALFLAG_CAMERA)
8751 r_refdef.view = myview;
8753 r_refdef.view.clipplane = p->plane;
8754 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8755 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8757 r_refdef.view.width = r_waterstate.camerawidth;
8758 r_refdef.view.height = r_waterstate.cameraheight;
8759 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8760 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8762 if(p->camera_entity)
8764 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8765 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8768 // note: all of the view is used for displaying... so
8769 // there is no use in scissoring
8771 // reverse the cullface settings for this render
8772 r_refdef.view.cullface_front = GL_FRONT;
8773 r_refdef.view.cullface_back = GL_BACK;
8774 // also reverse the view matrix
8775 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
8776 R_RenderView_UpdateViewVectors();
8777 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8779 r_refdef.view.usecustompvs = true;
8780 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);
8783 // camera needs no clipplane
8784 r_refdef.view.useclipplane = false;
8786 PlaneClassify(&r_refdef.view.clipplane);
8788 R_ResetViewRendering3D();
8789 R_ClearScreen(r_refdef.fogenabled);
8793 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);
8794 r_waterstate.renderingrefraction = false;
8798 r_waterstate.renderingscene = false;
8799 r_refdef.view = originalview;
8800 R_ResetViewRendering3D();
8801 R_ClearScreen(r_refdef.fogenabled);
8805 r_refdef.view = originalview;
8806 r_waterstate.renderingscene = false;
8807 Cvar_SetValueQuick(&r_water, 0);
8808 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
8812 void R_Bloom_StartFrame(void)
8814 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8816 switch(vid.renderpath)
8818 case RENDERPATH_GL20:
8819 case RENDERPATH_CGGL:
8820 case RENDERPATH_D3D9:
8821 case RENDERPATH_D3D10:
8822 case RENDERPATH_D3D11:
8824 case RENDERPATH_GL13:
8825 case RENDERPATH_GL11:
8829 // set bloomwidth and bloomheight to the bloom resolution that will be
8830 // used (often less than the screen resolution for faster rendering)
8831 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8832 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8833 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8834 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8835 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8837 // calculate desired texture sizes
8838 if (vid.support.arb_texture_non_power_of_two)
8840 screentexturewidth = r_refdef.view.width;
8841 screentextureheight = r_refdef.view.height;
8842 bloomtexturewidth = r_bloomstate.bloomwidth;
8843 bloomtextureheight = r_bloomstate.bloomheight;
8847 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
8848 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
8849 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
8850 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
8853 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))
8855 Cvar_SetValueQuick(&r_hdr, 0);
8856 Cvar_SetValueQuick(&r_bloom, 0);
8857 Cvar_SetValueQuick(&r_motionblur, 0);
8858 Cvar_SetValueQuick(&r_damageblur, 0);
8861 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)))
8862 screentexturewidth = screentextureheight = 0;
8863 if (!r_hdr.integer && !r_bloom.integer)
8864 bloomtexturewidth = bloomtextureheight = 0;
8866 // allocate textures as needed
8867 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8869 if (r_bloomstate.texture_screen)
8870 R_FreeTexture(r_bloomstate.texture_screen);
8871 r_bloomstate.texture_screen = NULL;
8872 r_bloomstate.screentexturewidth = screentexturewidth;
8873 r_bloomstate.screentextureheight = screentextureheight;
8874 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8875 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);
8877 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8879 if (r_bloomstate.texture_bloom)
8880 R_FreeTexture(r_bloomstate.texture_bloom);
8881 r_bloomstate.texture_bloom = NULL;
8882 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8883 r_bloomstate.bloomtextureheight = bloomtextureheight;
8884 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8885 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);
8888 // when doing a reduced render (HDR) we want to use a smaller area
8889 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8890 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8891 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8892 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8893 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8895 // set up a texcoord array for the full resolution screen image
8896 // (we have to keep this around to copy back during final render)
8897 r_bloomstate.screentexcoord2f[0] = 0;
8898 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
8899 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
8900 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
8901 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
8902 r_bloomstate.screentexcoord2f[5] = 0;
8903 r_bloomstate.screentexcoord2f[6] = 0;
8904 r_bloomstate.screentexcoord2f[7] = 0;
8906 // set up a texcoord array for the reduced resolution bloom image
8907 // (which will be additive blended over the screen image)
8908 r_bloomstate.bloomtexcoord2f[0] = 0;
8909 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8910 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8911 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8912 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8913 r_bloomstate.bloomtexcoord2f[5] = 0;
8914 r_bloomstate.bloomtexcoord2f[6] = 0;
8915 r_bloomstate.bloomtexcoord2f[7] = 0;
8917 switch(vid.renderpath)
8919 case RENDERPATH_GL11:
8920 case RENDERPATH_GL13:
8921 case RENDERPATH_GL20:
8922 case RENDERPATH_CGGL:
8924 case RENDERPATH_D3D9:
8925 case RENDERPATH_D3D10:
8926 case RENDERPATH_D3D11:
8929 for (i = 0;i < 4;i++)
8931 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
8932 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
8933 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
8934 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
8940 if (r_hdr.integer || r_bloom.integer)
8942 r_bloomstate.enabled = true;
8943 r_bloomstate.hdr = r_hdr.integer != 0;
8946 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);
8949 void R_Bloom_CopyBloomTexture(float colorscale)
8951 r_refdef.stats.bloom++;
8953 // scale down screen texture to the bloom texture size
8955 R_SetViewport(&r_bloomstate.viewport);
8956 GL_BlendFunc(GL_ONE, GL_ZERO);
8957 GL_Color(colorscale, colorscale, colorscale, 1);
8958 // 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...
8959 switch(vid.renderpath)
8961 case RENDERPATH_GL11:
8962 case RENDERPATH_GL13:
8963 case RENDERPATH_GL20:
8964 case RENDERPATH_CGGL:
8965 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8967 case RENDERPATH_D3D9:
8968 case RENDERPATH_D3D10:
8969 case RENDERPATH_D3D11:
8970 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8973 // TODO: do boxfilter scale-down in shader?
8974 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8975 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8976 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8978 // we now have a bloom image in the framebuffer
8979 // copy it into the bloom image texture for later processing
8980 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);
8981 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8984 void R_Bloom_CopyHDRTexture(void)
8986 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);
8987 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8990 void R_Bloom_MakeTexture(void)
8993 float xoffset, yoffset, r, brighten;
8995 r_refdef.stats.bloom++;
8997 R_ResetViewRendering2D();
8999 // we have a bloom image in the framebuffer
9001 R_SetViewport(&r_bloomstate.viewport);
9003 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
9006 r = bound(0, r_bloom_colorexponent.value / x, 1);
9007 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9009 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
9010 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9011 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9012 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9014 // copy the vertically blurred bloom view to a texture
9015 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);
9016 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9019 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
9020 brighten = r_bloom_brighten.value;
9022 brighten *= r_hdr_range.value;
9023 brighten = sqrt(brighten);
9025 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
9026 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9028 for (dir = 0;dir < 2;dir++)
9030 // blend on at multiple vertical offsets to achieve a vertical blur
9031 // TODO: do offset blends using GLSL
9032 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
9033 GL_BlendFunc(GL_ONE, GL_ZERO);
9034 for (x = -range;x <= range;x++)
9036 if (!dir){xoffset = 0;yoffset = x;}
9037 else {xoffset = x;yoffset = 0;}
9038 xoffset /= (float)r_bloomstate.bloomtexturewidth;
9039 yoffset /= (float)r_bloomstate.bloomtextureheight;
9040 // compute a texcoord array with the specified x and y offset
9041 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
9042 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9043 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9044 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9045 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9046 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
9047 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
9048 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
9049 // this r value looks like a 'dot' particle, fading sharply to
9050 // black at the edges
9051 // (probably not realistic but looks good enough)
9052 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
9053 //r = brighten/(range*2+1);
9054 r = brighten / (range * 2 + 1);
9056 r *= (1 - x*x/(float)(range*range));
9057 GL_Color(r, r, r, 1);
9058 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
9059 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9060 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9061 GL_BlendFunc(GL_ONE, GL_ONE);
9064 // copy the vertically blurred bloom view to a texture
9065 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);
9066 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9070 void R_HDR_RenderBloomTexture(void)
9072 int oldwidth, oldheight;
9073 float oldcolorscale;
9075 oldcolorscale = r_refdef.view.colorscale;
9076 oldwidth = r_refdef.view.width;
9077 oldheight = r_refdef.view.height;
9078 r_refdef.view.width = r_bloomstate.bloomwidth;
9079 r_refdef.view.height = r_bloomstate.bloomheight;
9081 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
9082 // TODO: add exposure compensation features
9083 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
9085 r_refdef.view.showdebug = false;
9086 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
9088 R_ResetViewRendering3D();
9090 R_ClearScreen(r_refdef.fogenabled);
9091 if (r_timereport_active)
9092 R_TimeReport("HDRclear");
9095 if (r_timereport_active)
9096 R_TimeReport("visibility");
9098 // only do secondary renders with HDR if r_hdr is 2 or higher
9099 r_waterstate.numwaterplanes = 0;
9100 if (r_waterstate.enabled && r_hdr.integer >= 2)
9101 R_RenderWaterPlanes();
9103 r_refdef.view.showdebug = true;
9105 r_waterstate.numwaterplanes = 0;
9107 R_ResetViewRendering2D();
9109 R_Bloom_CopyHDRTexture();
9110 R_Bloom_MakeTexture();
9112 // restore the view settings
9113 r_refdef.view.width = oldwidth;
9114 r_refdef.view.height = oldheight;
9115 r_refdef.view.colorscale = oldcolorscale;
9117 R_ResetViewRendering3D();
9119 R_ClearScreen(r_refdef.fogenabled);
9120 if (r_timereport_active)
9121 R_TimeReport("viewclear");
9124 static void R_BlendView(void)
9126 unsigned int permutation;
9127 float uservecs[4][4];
9129 switch (vid.renderpath)
9131 case RENDERPATH_GL20:
9132 case RENDERPATH_CGGL:
9133 case RENDERPATH_D3D9:
9134 case RENDERPATH_D3D10:
9135 case RENDERPATH_D3D11:
9137 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
9138 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
9139 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
9140 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
9141 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
9143 if (r_bloomstate.texture_screen)
9145 // make sure the buffer is available
9146 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
9148 R_ResetViewRendering2D();
9150 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
9152 // declare variables
9154 static float avgspeed;
9156 speed = VectorLength(cl.movement_velocity);
9158 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
9159 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
9161 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
9162 speed = bound(0, speed, 1);
9163 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
9165 // calculate values into a standard alpha
9166 cl.motionbluralpha = 1 - exp(-
9168 (r_motionblur.value * speed / 80)
9170 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
9173 max(0.0001, cl.time - cl.oldtime) // fps independent
9176 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
9177 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
9179 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
9181 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9182 GL_Color(1, 1, 1, cl.motionbluralpha);
9183 switch(vid.renderpath)
9185 case RENDERPATH_GL11:
9186 case RENDERPATH_GL13:
9187 case RENDERPATH_GL20:
9188 case RENDERPATH_CGGL:
9189 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9191 case RENDERPATH_D3D9:
9192 case RENDERPATH_D3D10:
9193 case RENDERPATH_D3D11:
9194 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9197 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9198 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9199 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9203 // copy view into the screen texture
9204 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);
9205 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9207 else if (!r_bloomstate.texture_bloom)
9209 // we may still have to do view tint...
9210 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9212 // apply a color tint to the whole view
9213 R_ResetViewRendering2D();
9214 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9215 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9216 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9217 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9218 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9220 break; // no screen processing, no bloom, skip it
9223 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9225 // render simple bloom effect
9226 // copy the screen and shrink it and darken it for the bloom process
9227 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9228 // make the bloom texture
9229 R_Bloom_MakeTexture();
9232 #if _MSC_VER >= 1400
9233 #define sscanf sscanf_s
9235 memset(uservecs, 0, sizeof(uservecs));
9236 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9237 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9238 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9239 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9241 R_ResetViewRendering2D();
9242 GL_Color(1, 1, 1, 1);
9243 GL_BlendFunc(GL_ONE, GL_ZERO);
9245 switch(vid.renderpath)
9247 case RENDERPATH_GL20:
9248 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9249 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9250 if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
9251 if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
9252 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
9253 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]);
9254 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9255 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]);
9256 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]);
9257 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]);
9258 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]);
9259 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
9260 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9261 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);
9263 case RENDERPATH_CGGL:
9265 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9266 R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9267 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_bloomstate.texture_screen);CHECKCGERROR
9268 if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_bloomstate.texture_bloom );CHECKCGERROR
9269 if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps );CHECKCGERROR
9270 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
9271 if (r_cg_permutation->fp_PixelSize ) cgGLSetParameter2f( r_cg_permutation->fp_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9272 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
9273 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
9274 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
9275 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
9276 if (r_cg_permutation->fp_Saturation ) cgGLSetParameter1f( r_cg_permutation->fp_Saturation , r_glsl_saturation.value);CHECKCGERROR
9277 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9278 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);
9281 case RENDERPATH_D3D9:
9283 // 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...
9284 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9285 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9286 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
9287 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
9288 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
9289 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9290 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9291 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9292 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9293 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9294 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9295 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
9296 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9297 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9300 case RENDERPATH_D3D10:
9301 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9303 case RENDERPATH_D3D11:
9304 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9309 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9310 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9312 case RENDERPATH_GL13:
9313 case RENDERPATH_GL11:
9314 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9316 // apply a color tint to the whole view
9317 R_ResetViewRendering2D();
9318 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9319 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9320 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9321 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9322 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9328 matrix4x4_t r_waterscrollmatrix;
9330 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9332 if (r_refdef.fog_density)
9334 r_refdef.fogcolor[0] = r_refdef.fog_red;
9335 r_refdef.fogcolor[1] = r_refdef.fog_green;
9336 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9338 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9339 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9340 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9341 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9345 VectorCopy(r_refdef.fogcolor, fogvec);
9346 // color.rgb *= ContrastBoost * SceneBrightness;
9347 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9348 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9349 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9350 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9355 void R_UpdateVariables(void)
9359 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9361 r_refdef.farclip = r_farclip_base.value;
9362 if (r_refdef.scene.worldmodel)
9363 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9364 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9366 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9367 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9368 r_refdef.polygonfactor = 0;
9369 r_refdef.polygonoffset = 0;
9370 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9371 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9373 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9374 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9375 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
9376 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9377 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9378 if (FAKELIGHT_ENABLED)
9380 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
9382 if (r_showsurfaces.integer)
9384 r_refdef.scene.rtworld = false;
9385 r_refdef.scene.rtworldshadows = false;
9386 r_refdef.scene.rtdlight = false;
9387 r_refdef.scene.rtdlightshadows = false;
9388 r_refdef.lightmapintensity = 0;
9391 if (gamemode == GAME_NEHAHRA)
9393 if (gl_fogenable.integer)
9395 r_refdef.oldgl_fogenable = true;
9396 r_refdef.fog_density = gl_fogdensity.value;
9397 r_refdef.fog_red = gl_fogred.value;
9398 r_refdef.fog_green = gl_foggreen.value;
9399 r_refdef.fog_blue = gl_fogblue.value;
9400 r_refdef.fog_alpha = 1;
9401 r_refdef.fog_start = 0;
9402 r_refdef.fog_end = gl_skyclip.value;
9403 r_refdef.fog_height = 1<<30;
9404 r_refdef.fog_fadedepth = 128;
9406 else if (r_refdef.oldgl_fogenable)
9408 r_refdef.oldgl_fogenable = false;
9409 r_refdef.fog_density = 0;
9410 r_refdef.fog_red = 0;
9411 r_refdef.fog_green = 0;
9412 r_refdef.fog_blue = 0;
9413 r_refdef.fog_alpha = 0;
9414 r_refdef.fog_start = 0;
9415 r_refdef.fog_end = 0;
9416 r_refdef.fog_height = 1<<30;
9417 r_refdef.fog_fadedepth = 128;
9421 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9422 r_refdef.fog_start = max(0, r_refdef.fog_start);
9423 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9425 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9427 if (r_refdef.fog_density && r_drawfog.integer)
9429 r_refdef.fogenabled = true;
9430 // this is the point where the fog reaches 0.9986 alpha, which we
9431 // consider a good enough cutoff point for the texture
9432 // (0.9986 * 256 == 255.6)
9433 if (r_fog_exp2.integer)
9434 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9436 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9437 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9438 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9439 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9440 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9441 R_BuildFogHeightTexture();
9442 // fog color was already set
9443 // update the fog texture
9444 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)
9445 R_BuildFogTexture();
9446 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9447 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9450 r_refdef.fogenabled = false;
9452 switch(vid.renderpath)
9454 case RENDERPATH_GL20:
9455 case RENDERPATH_CGGL:
9456 case RENDERPATH_D3D9:
9457 case RENDERPATH_D3D10:
9458 case RENDERPATH_D3D11:
9459 if(v_glslgamma.integer && !vid_gammatables_trivial)
9461 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9463 // build GLSL gamma texture
9464 #define RAMPWIDTH 256
9465 unsigned short ramp[RAMPWIDTH * 3];
9466 unsigned char rampbgr[RAMPWIDTH][4];
9469 r_texture_gammaramps_serial = vid_gammatables_serial;
9471 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9472 for(i = 0; i < RAMPWIDTH; ++i)
9474 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9475 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9476 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9479 if (r_texture_gammaramps)
9481 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9485 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9491 // remove GLSL gamma texture
9494 case RENDERPATH_GL13:
9495 case RENDERPATH_GL11:
9500 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9501 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9507 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9508 if( scenetype != r_currentscenetype ) {
9509 // store the old scenetype
9510 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9511 r_currentscenetype = scenetype;
9512 // move in the new scene
9513 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9522 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9524 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9525 if( scenetype == r_currentscenetype ) {
9526 return &r_refdef.scene;
9528 return &r_scenes_store[ scenetype ];
9537 void R_RenderView(void)
9539 if (r_timereport_active)
9540 R_TimeReport("start");
9541 r_textureframe++; // used only by R_GetCurrentTexture
9542 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9544 if (!r_drawentities.integer)
9545 r_refdef.scene.numentities = 0;
9547 R_AnimCache_ClearCache();
9548 R_FrameData_NewFrame();
9550 if (r_refdef.view.isoverlay)
9552 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9553 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9554 R_TimeReport("depthclear");
9556 r_refdef.view.showdebug = false;
9558 r_waterstate.enabled = false;
9559 r_waterstate.numwaterplanes = 0;
9567 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9568 return; //Host_Error ("R_RenderView: NULL worldmodel");
9570 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9572 R_RenderView_UpdateViewVectors();
9574 R_Shadow_UpdateWorldLightSelection();
9576 R_Bloom_StartFrame();
9577 R_Water_StartFrame();
9580 if (r_timereport_active)
9581 R_TimeReport("viewsetup");
9583 R_ResetViewRendering3D();
9585 if (r_refdef.view.clear || r_refdef.fogenabled)
9587 R_ClearScreen(r_refdef.fogenabled);
9588 if (r_timereport_active)
9589 R_TimeReport("viewclear");
9591 r_refdef.view.clear = true;
9593 // this produces a bloom texture to be used in R_BlendView() later
9594 if (r_hdr.integer && r_bloomstate.bloomwidth)
9596 R_HDR_RenderBloomTexture();
9597 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9598 r_textureframe++; // used only by R_GetCurrentTexture
9601 r_refdef.view.showdebug = true;
9604 if (r_timereport_active)
9605 R_TimeReport("visibility");
9607 r_waterstate.numwaterplanes = 0;
9608 if (r_waterstate.enabled)
9609 R_RenderWaterPlanes();
9612 r_waterstate.numwaterplanes = 0;
9615 if (r_timereport_active)
9616 R_TimeReport("blendview");
9618 GL_Scissor(0, 0, vid.width, vid.height);
9619 GL_ScissorTest(false);
9624 void R_RenderWaterPlanes(void)
9626 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9628 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9629 if (r_timereport_active)
9630 R_TimeReport("waterworld");
9633 // don't let sound skip if going slow
9634 if (r_refdef.scene.extraupdate)
9637 R_DrawModelsAddWaterPlanes();
9638 if (r_timereport_active)
9639 R_TimeReport("watermodels");
9641 if (r_waterstate.numwaterplanes)
9643 R_Water_ProcessPlanes();
9644 if (r_timereport_active)
9645 R_TimeReport("waterscenes");
9649 extern void R_DrawLightningBeams (void);
9650 extern void VM_CL_AddPolygonsToMeshQueue (void);
9651 extern void R_DrawPortals (void);
9652 extern cvar_t cl_locs_show;
9653 static void R_DrawLocs(void);
9654 static void R_DrawEntityBBoxes(void);
9655 static void R_DrawModelDecals(void);
9656 extern void R_DrawModelShadows(void);
9657 extern void R_DrawModelShadowMaps(void);
9658 extern cvar_t cl_decals_newsystem;
9659 extern qboolean r_shadow_usingdeferredprepass;
9660 void R_RenderScene(void)
9662 qboolean shadowmapping = false;
9664 if (r_timereport_active)
9665 R_TimeReport("beginscene");
9667 r_refdef.stats.renders++;
9671 // don't let sound skip if going slow
9672 if (r_refdef.scene.extraupdate)
9675 R_MeshQueue_BeginScene();
9679 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);
9681 if (r_timereport_active)
9682 R_TimeReport("skystartframe");
9684 if (cl.csqc_vidvars.drawworld)
9686 // don't let sound skip if going slow
9687 if (r_refdef.scene.extraupdate)
9690 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9692 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9693 if (r_timereport_active)
9694 R_TimeReport("worldsky");
9697 if (R_DrawBrushModelsSky() && r_timereport_active)
9698 R_TimeReport("bmodelsky");
9700 if (skyrendermasked && skyrenderlater)
9702 // we have to force off the water clipping plane while rendering sky
9706 if (r_timereport_active)
9707 R_TimeReport("sky");
9711 R_AnimCache_CacheVisibleEntities();
9712 if (r_timereport_active)
9713 R_TimeReport("animation");
9715 R_Shadow_PrepareLights();
9716 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9717 R_Shadow_PrepareModelShadows();
9718 if (r_timereport_active)
9719 R_TimeReport("preparelights");
9721 if (R_Shadow_ShadowMappingEnabled())
9722 shadowmapping = true;
9724 if (r_shadow_usingdeferredprepass)
9725 R_Shadow_DrawPrepass();
9727 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9729 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9730 if (r_timereport_active)
9731 R_TimeReport("worlddepth");
9733 if (r_depthfirst.integer >= 2)
9735 R_DrawModelsDepth();
9736 if (r_timereport_active)
9737 R_TimeReport("modeldepth");
9740 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9742 R_DrawModelShadowMaps();
9743 R_ResetViewRendering3D();
9744 // don't let sound skip if going slow
9745 if (r_refdef.scene.extraupdate)
9749 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9751 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9752 if (r_timereport_active)
9753 R_TimeReport("world");
9756 // don't let sound skip if going slow
9757 if (r_refdef.scene.extraupdate)
9761 if (r_timereport_active)
9762 R_TimeReport("models");
9764 // don't let sound skip if going slow
9765 if (r_refdef.scene.extraupdate)
9768 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9770 R_DrawModelShadows();
9771 R_ResetViewRendering3D();
9772 // don't let sound skip if going slow
9773 if (r_refdef.scene.extraupdate)
9777 if (!r_shadow_usingdeferredprepass)
9779 R_Shadow_DrawLights();
9780 if (r_timereport_active)
9781 R_TimeReport("rtlights");
9784 // don't let sound skip if going slow
9785 if (r_refdef.scene.extraupdate)
9788 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9790 R_DrawModelShadows();
9791 R_ResetViewRendering3D();
9792 // don't let sound skip if going slow
9793 if (r_refdef.scene.extraupdate)
9797 if (cl.csqc_vidvars.drawworld)
9799 if (cl_decals_newsystem.integer)
9801 R_DrawModelDecals();
9802 if (r_timereport_active)
9803 R_TimeReport("modeldecals");
9808 if (r_timereport_active)
9809 R_TimeReport("decals");
9813 if (r_timereport_active)
9814 R_TimeReport("particles");
9817 if (r_timereport_active)
9818 R_TimeReport("explosions");
9820 R_DrawLightningBeams();
9821 if (r_timereport_active)
9822 R_TimeReport("lightning");
9825 VM_CL_AddPolygonsToMeshQueue();
9827 if (r_refdef.view.showdebug)
9829 if (cl_locs_show.integer)
9832 if (r_timereport_active)
9833 R_TimeReport("showlocs");
9836 if (r_drawportals.integer)
9839 if (r_timereport_active)
9840 R_TimeReport("portals");
9843 if (r_showbboxes.value > 0)
9845 R_DrawEntityBBoxes();
9846 if (r_timereport_active)
9847 R_TimeReport("bboxes");
9851 R_MeshQueue_RenderTransparent();
9852 if (r_timereport_active)
9853 R_TimeReport("drawtrans");
9855 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))
9857 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9858 if (r_timereport_active)
9859 R_TimeReport("worlddebug");
9860 R_DrawModelsDebug();
9861 if (r_timereport_active)
9862 R_TimeReport("modeldebug");
9865 if (cl.csqc_vidvars.drawworld)
9867 R_Shadow_DrawCoronas();
9868 if (r_timereport_active)
9869 R_TimeReport("coronas");
9874 GL_DepthTest(false);
9875 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9876 GL_Color(1, 1, 1, 1);
9877 qglBegin(GL_POLYGON);
9878 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
9879 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
9880 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
9881 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
9883 qglBegin(GL_POLYGON);
9884 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]);
9885 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]);
9886 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]);
9887 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]);
9889 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9893 // don't let sound skip if going slow
9894 if (r_refdef.scene.extraupdate)
9897 R_ResetViewRendering2D();
9900 static const unsigned short bboxelements[36] =
9910 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9913 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9915 RSurf_ActiveWorldEntity();
9917 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9918 GL_DepthMask(false);
9919 GL_DepthRange(0, 1);
9920 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9921 R_Mesh_ResetTextureState();
9923 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9924 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9925 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9926 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9927 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9928 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9929 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9930 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9931 R_FillColors(color4f, 8, cr, cg, cb, ca);
9932 if (r_refdef.fogenabled)
9934 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9936 f1 = RSurf_FogVertex(v);
9938 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9939 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9940 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9943 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
9944 R_Mesh_ResetTextureState();
9945 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9946 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
9949 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9953 prvm_edict_t *edict;
9954 prvm_prog_t *prog_save = prog;
9956 // this function draws bounding boxes of server entities
9960 GL_CullFace(GL_NONE);
9961 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9965 for (i = 0;i < numsurfaces;i++)
9967 edict = PRVM_EDICT_NUM(surfacelist[i]);
9968 switch ((int)edict->fields.server->solid)
9970 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
9971 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
9972 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
9973 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9974 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
9975 default: Vector4Set(color, 0, 0, 0, 0.50);break;
9977 color[3] *= r_showbboxes.value;
9978 color[3] = bound(0, color[3], 1);
9979 GL_DepthTest(!r_showdisabledepthtest.integer);
9980 GL_CullFace(r_refdef.view.cullface_front);
9981 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
9987 static void R_DrawEntityBBoxes(void)
9990 prvm_edict_t *edict;
9992 prvm_prog_t *prog_save = prog;
9994 // this function draws bounding boxes of server entities
10000 for (i = 0;i < prog->num_edicts;i++)
10002 edict = PRVM_EDICT_NUM(i);
10003 if (edict->priv.server->free)
10005 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
10006 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
10008 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
10010 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
10011 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
10017 static const int nomodelelement3i[24] =
10029 static const unsigned short nomodelelement3s[24] =
10041 static const float nomodelvertex3f[6*3] =
10051 static const float nomodelcolor4f[6*4] =
10053 0.0f, 0.0f, 0.5f, 1.0f,
10054 0.0f, 0.0f, 0.5f, 1.0f,
10055 0.0f, 0.5f, 0.0f, 1.0f,
10056 0.0f, 0.5f, 0.0f, 1.0f,
10057 0.5f, 0.0f, 0.0f, 1.0f,
10058 0.5f, 0.0f, 0.0f, 1.0f
10061 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10065 float color4f[6*4];
10067 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);
10069 // this is only called once per entity so numsurfaces is always 1, and
10070 // surfacelist is always {0}, so this code does not handle batches
10072 if (rsurface.ent_flags & RENDER_ADDITIVE)
10074 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
10075 GL_DepthMask(false);
10077 else if (rsurface.colormod[3] < 1)
10079 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10080 GL_DepthMask(false);
10084 GL_BlendFunc(GL_ONE, GL_ZERO);
10085 GL_DepthMask(true);
10087 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
10088 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
10089 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
10090 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
10091 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10092 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
10093 for (i = 0, c = color4f;i < 6;i++, c += 4)
10095 c[0] *= rsurface.colormod[0];
10096 c[1] *= rsurface.colormod[1];
10097 c[2] *= rsurface.colormod[2];
10098 c[3] *= rsurface.colormod[3];
10100 if (r_refdef.fogenabled)
10102 for (i = 0, c = color4f;i < 6;i++, c += 4)
10104 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
10106 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
10107 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
10108 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
10111 R_Mesh_ResetTextureState();
10112 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
10113 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
10116 void R_DrawNoModel(entity_render_t *ent)
10119 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
10120 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
10121 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
10123 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
10126 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
10128 vec3_t right1, right2, diff, normal;
10130 VectorSubtract (org2, org1, normal);
10132 // calculate 'right' vector for start
10133 VectorSubtract (r_refdef.view.origin, org1, diff);
10134 CrossProduct (normal, diff, right1);
10135 VectorNormalize (right1);
10137 // calculate 'right' vector for end
10138 VectorSubtract (r_refdef.view.origin, org2, diff);
10139 CrossProduct (normal, diff, right2);
10140 VectorNormalize (right2);
10142 vert[ 0] = org1[0] + width * right1[0];
10143 vert[ 1] = org1[1] + width * right1[1];
10144 vert[ 2] = org1[2] + width * right1[2];
10145 vert[ 3] = org1[0] - width * right1[0];
10146 vert[ 4] = org1[1] - width * right1[1];
10147 vert[ 5] = org1[2] - width * right1[2];
10148 vert[ 6] = org2[0] - width * right2[0];
10149 vert[ 7] = org2[1] - width * right2[1];
10150 vert[ 8] = org2[2] - width * right2[2];
10151 vert[ 9] = org2[0] + width * right2[0];
10152 vert[10] = org2[1] + width * right2[1];
10153 vert[11] = org2[2] + width * right2[2];
10156 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)
10158 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
10159 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
10160 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
10161 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
10162 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
10163 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
10164 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
10165 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
10166 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
10167 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
10168 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
10169 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
10172 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
10177 VectorSet(v, x, y, z);
10178 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
10179 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
10181 if (i == mesh->numvertices)
10183 if (mesh->numvertices < mesh->maxvertices)
10185 VectorCopy(v, vertex3f);
10186 mesh->numvertices++;
10188 return mesh->numvertices;
10194 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
10197 int *e, element[3];
10198 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10199 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10200 e = mesh->element3i + mesh->numtriangles * 3;
10201 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
10203 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
10204 if (mesh->numtriangles < mesh->maxtriangles)
10209 mesh->numtriangles++;
10211 element[1] = element[2];
10215 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
10218 int *e, element[3];
10219 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10220 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10221 e = mesh->element3i + mesh->numtriangles * 3;
10222 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10224 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10225 if (mesh->numtriangles < mesh->maxtriangles)
10230 mesh->numtriangles++;
10232 element[1] = element[2];
10236 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10237 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10239 int planenum, planenum2;
10242 mplane_t *plane, *plane2;
10244 double temppoints[2][256*3];
10245 // figure out how large a bounding box we need to properly compute this brush
10247 for (w = 0;w < numplanes;w++)
10248 maxdist = max(maxdist, fabs(planes[w].dist));
10249 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10250 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10251 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10255 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10256 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10258 if (planenum2 == planenum)
10260 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);
10263 if (tempnumpoints < 3)
10265 // generate elements forming a triangle fan for this polygon
10266 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10270 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)
10272 texturelayer_t *layer;
10273 layer = t->currentlayers + t->currentnumlayers++;
10274 layer->type = type;
10275 layer->depthmask = depthmask;
10276 layer->blendfunc1 = blendfunc1;
10277 layer->blendfunc2 = blendfunc2;
10278 layer->texture = texture;
10279 layer->texmatrix = *matrix;
10280 layer->color[0] = r;
10281 layer->color[1] = g;
10282 layer->color[2] = b;
10283 layer->color[3] = a;
10286 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10288 if(parms[0] == 0 && parms[1] == 0)
10290 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10291 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10296 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10299 index = parms[2] + r_refdef.scene.time * parms[3];
10300 index -= floor(index);
10301 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10304 case Q3WAVEFUNC_NONE:
10305 case Q3WAVEFUNC_NOISE:
10306 case Q3WAVEFUNC_COUNT:
10309 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10310 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10311 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10312 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10313 case Q3WAVEFUNC_TRIANGLE:
10315 f = index - floor(index);
10318 else if (index < 2)
10320 else if (index < 3)
10326 f = parms[0] + parms[1] * f;
10327 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10328 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10332 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10337 matrix4x4_t matrix, temp;
10338 switch(tcmod->tcmod)
10340 case Q3TCMOD_COUNT:
10342 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10343 matrix = r_waterscrollmatrix;
10345 matrix = identitymatrix;
10347 case Q3TCMOD_ENTITYTRANSLATE:
10348 // this is used in Q3 to allow the gamecode to control texcoord
10349 // scrolling on the entity, which is not supported in darkplaces yet.
10350 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10352 case Q3TCMOD_ROTATE:
10353 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10354 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10355 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10357 case Q3TCMOD_SCALE:
10358 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10360 case Q3TCMOD_SCROLL:
10361 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10363 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10364 w = (int) tcmod->parms[0];
10365 h = (int) tcmod->parms[1];
10366 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10368 idx = (int) floor(f * w * h);
10369 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10371 case Q3TCMOD_STRETCH:
10372 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10373 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10375 case Q3TCMOD_TRANSFORM:
10376 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
10377 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
10378 VectorSet(tcmat + 6, 0 , 0 , 1);
10379 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
10380 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10382 case Q3TCMOD_TURBULENT:
10383 // this is handled in the RSurf_PrepareVertices function
10384 matrix = identitymatrix;
10388 Matrix4x4_Concat(texmatrix, &matrix, &temp);
10391 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10393 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10394 char name[MAX_QPATH];
10395 skinframe_t *skinframe;
10396 unsigned char pixels[296*194];
10397 strlcpy(cache->name, skinname, sizeof(cache->name));
10398 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10399 if (developer_loading.integer)
10400 Con_Printf("loading %s\n", name);
10401 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10402 if (!skinframe || !skinframe->base)
10405 fs_offset_t filesize;
10407 f = FS_LoadFile(name, tempmempool, true, &filesize);
10410 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10411 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10415 cache->skinframe = skinframe;
10418 texture_t *R_GetCurrentTexture(texture_t *t)
10421 const entity_render_t *ent = rsurface.entity;
10422 dp_model_t *model = ent->model;
10423 q3shaderinfo_layer_tcmod_t *tcmod;
10425 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10426 return t->currentframe;
10427 t->update_lastrenderframe = r_textureframe;
10428 t->update_lastrenderentity = (void *)ent;
10430 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10431 t->camera_entity = ent->entitynumber;
10433 t->camera_entity = 0;
10435 // switch to an alternate material if this is a q1bsp animated material
10437 texture_t *texture = t;
10438 int s = rsurface.ent_skinnum;
10439 if ((unsigned int)s >= (unsigned int)model->numskins)
10441 if (model->skinscenes)
10443 if (model->skinscenes[s].framecount > 1)
10444 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10446 s = model->skinscenes[s].firstframe;
10449 t = t + s * model->num_surfaces;
10452 // use an alternate animation if the entity's frame is not 0,
10453 // and only if the texture has an alternate animation
10454 if (rsurface.ent_alttextures && t->anim_total[1])
10455 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10457 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10459 texture->currentframe = t;
10462 // update currentskinframe to be a qw skin or animation frame
10463 if (rsurface.ent_qwskin >= 0)
10465 i = rsurface.ent_qwskin;
10466 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10468 r_qwskincache_size = cl.maxclients;
10470 Mem_Free(r_qwskincache);
10471 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10473 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10474 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10475 t->currentskinframe = r_qwskincache[i].skinframe;
10476 if (t->currentskinframe == NULL)
10477 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10479 else if (t->numskinframes >= 2)
10480 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10481 if (t->backgroundnumskinframes >= 2)
10482 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10484 t->currentmaterialflags = t->basematerialflags;
10485 t->currentalpha = rsurface.colormod[3];
10486 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10487 t->currentalpha *= r_wateralpha.value;
10488 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10489 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10490 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10491 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10492 if (!(rsurface.ent_flags & RENDER_LIGHT))
10493 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10494 else if (FAKELIGHT_ENABLED)
10496 // no modellight if using fakelight for the map
10498 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10500 // pick a model lighting mode
10501 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10502 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10504 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10506 if (rsurface.ent_flags & RENDER_ADDITIVE)
10507 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10508 else if (t->currentalpha < 1)
10509 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10510 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10511 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10512 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10513 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10514 if (t->backgroundnumskinframes)
10515 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10516 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10518 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10519 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10522 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10523 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10524 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10526 // there is no tcmod
10527 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10529 t->currenttexmatrix = r_waterscrollmatrix;
10530 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10532 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10534 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10535 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10538 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10539 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10540 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10541 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10543 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10544 if (t->currentskinframe->qpixels)
10545 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10546 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10547 if (!t->basetexture)
10548 t->basetexture = r_texture_notexture;
10549 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10550 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10551 t->nmaptexture = t->currentskinframe->nmap;
10552 if (!t->nmaptexture)
10553 t->nmaptexture = r_texture_blanknormalmap;
10554 t->glosstexture = r_texture_black;
10555 t->glowtexture = t->currentskinframe->glow;
10556 t->fogtexture = t->currentskinframe->fog;
10557 t->reflectmasktexture = t->currentskinframe->reflect;
10558 if (t->backgroundnumskinframes)
10560 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10561 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10562 t->backgroundglosstexture = r_texture_black;
10563 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10564 if (!t->backgroundnmaptexture)
10565 t->backgroundnmaptexture = r_texture_blanknormalmap;
10569 t->backgroundbasetexture = r_texture_white;
10570 t->backgroundnmaptexture = r_texture_blanknormalmap;
10571 t->backgroundglosstexture = r_texture_black;
10572 t->backgroundglowtexture = NULL;
10574 t->specularpower = r_shadow_glossexponent.value;
10575 // TODO: store reference values for these in the texture?
10576 t->specularscale = 0;
10577 if (r_shadow_gloss.integer > 0)
10579 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10581 if (r_shadow_glossintensity.value > 0)
10583 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10584 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10585 t->specularscale = r_shadow_glossintensity.value;
10588 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10590 t->glosstexture = r_texture_white;
10591 t->backgroundglosstexture = r_texture_white;
10592 t->specularscale = r_shadow_gloss2intensity.value;
10593 t->specularpower = r_shadow_gloss2exponent.value;
10596 t->specularscale *= t->specularscalemod;
10597 t->specularpower *= t->specularpowermod;
10599 // lightmaps mode looks bad with dlights using actual texturing, so turn
10600 // off the colormap and glossmap, but leave the normalmap on as it still
10601 // accurately represents the shading involved
10602 if (gl_lightmaps.integer)
10604 t->basetexture = r_texture_grey128;
10605 t->pantstexture = r_texture_black;
10606 t->shirttexture = r_texture_black;
10607 t->nmaptexture = r_texture_blanknormalmap;
10608 t->glosstexture = r_texture_black;
10609 t->glowtexture = NULL;
10610 t->fogtexture = NULL;
10611 t->reflectmasktexture = NULL;
10612 t->backgroundbasetexture = NULL;
10613 t->backgroundnmaptexture = r_texture_blanknormalmap;
10614 t->backgroundglosstexture = r_texture_black;
10615 t->backgroundglowtexture = NULL;
10616 t->specularscale = 0;
10617 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10620 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10621 VectorClear(t->dlightcolor);
10622 t->currentnumlayers = 0;
10623 if (t->currentmaterialflags & MATERIALFLAG_WALL)
10625 int blendfunc1, blendfunc2;
10626 qboolean depthmask;
10627 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10629 blendfunc1 = GL_SRC_ALPHA;
10630 blendfunc2 = GL_ONE;
10632 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10634 blendfunc1 = GL_SRC_ALPHA;
10635 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10637 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10639 blendfunc1 = t->customblendfunc[0];
10640 blendfunc2 = t->customblendfunc[1];
10644 blendfunc1 = GL_ONE;
10645 blendfunc2 = GL_ZERO;
10647 // don't colormod evilblend textures
10648 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10649 VectorSet(t->lightmapcolor, 1, 1, 1);
10650 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10651 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10653 // fullbright is not affected by r_refdef.lightmapintensity
10654 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]);
10655 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10656 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]);
10657 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10658 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]);
10662 vec3_t ambientcolor;
10664 // set the color tint used for lights affecting this surface
10665 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10667 // q3bsp has no lightmap updates, so the lightstylevalue that
10668 // would normally be baked into the lightmap must be
10669 // applied to the color
10670 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10671 if (model->type == mod_brushq3)
10672 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10673 colorscale *= r_refdef.lightmapintensity;
10674 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10675 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10676 // basic lit geometry
10677 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]);
10678 // add pants/shirt if needed
10679 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10680 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]);
10681 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10682 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]);
10683 // now add ambient passes if needed
10684 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10686 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]);
10687 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10688 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]);
10689 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10690 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]);
10693 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10694 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]);
10695 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10697 // if this is opaque use alpha blend which will darken the earlier
10700 // if this is an alpha blended material, all the earlier passes
10701 // were darkened by fog already, so we only need to add the fog
10702 // color ontop through the fog mask texture
10704 // if this is an additive blended material, all the earlier passes
10705 // were darkened by fog already, and we should not add fog color
10706 // (because the background was not darkened, there is no fog color
10707 // that was lost behind it).
10708 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]);
10712 return t->currentframe;
10715 rsurfacestate_t rsurface;
10717 void R_Mesh_ResizeArrays(int newvertices)
10719 unsigned char *base;
10721 if (rsurface.array_size >= newvertices)
10723 if (rsurface.array_base)
10724 Mem_Free(rsurface.array_base);
10725 rsurface.array_size = (newvertices + 1023) & ~1023;
10727 size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10728 size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10729 size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10730 size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10731 size += rsurface.array_size * sizeof(float[3]);
10732 size += rsurface.array_size * sizeof(float[3]);
10733 size += rsurface.array_size * sizeof(float[3]);
10734 size += rsurface.array_size * sizeof(float[3]);
10735 size += rsurface.array_size * sizeof(float[3]);
10736 size += rsurface.array_size * sizeof(float[3]);
10737 size += rsurface.array_size * sizeof(float[3]);
10738 size += rsurface.array_size * sizeof(float[3]);
10739 size += rsurface.array_size * sizeof(float[4]);
10740 size += rsurface.array_size * sizeof(float[2]);
10741 size += rsurface.array_size * sizeof(float[2]);
10742 size += rsurface.array_size * sizeof(float[4]);
10743 size += rsurface.array_size * sizeof(int[3]);
10744 size += rsurface.array_size * sizeof(unsigned short[3]);
10745 rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
10746 rsurface.array_modelvertexmesh = (r_vertexmesh_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10747 rsurface.array_batchvertexmesh = (r_vertexmesh_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10748 rsurface.array_modelvertexposition = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10749 rsurface.array_batchvertexposition = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10750 rsurface.array_modelvertex3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10751 rsurface.array_modelsvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10752 rsurface.array_modeltvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10753 rsurface.array_modelnormal3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10754 rsurface.array_batchvertex3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10755 rsurface.array_batchsvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10756 rsurface.array_batchtvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10757 rsurface.array_batchnormal3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10758 rsurface.array_batchlightmapcolor4f = (float *)base;base += rsurface.array_size * sizeof(float[4]);
10759 rsurface.array_batchtexcoordtexture2f = (float *)base;base += rsurface.array_size * sizeof(float[2]);
10760 rsurface.array_batchtexcoordlightmap2f = (float *)base;base += rsurface.array_size * sizeof(float[2]);
10761 rsurface.array_passcolor4f = (float *)base;base += rsurface.array_size * sizeof(float[4]);
10762 rsurface.array_batchelement3i = (int *)base;base += rsurface.array_size * sizeof(int[3]);
10763 rsurface.array_batchelement3s = (unsigned short *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
10766 void RSurf_ActiveWorldEntity(void)
10768 dp_model_t *model = r_refdef.scene.worldmodel;
10769 //if (rsurface.entity == r_refdef.scene.worldentity)
10771 rsurface.entity = r_refdef.scene.worldentity;
10772 rsurface.skeleton = NULL;
10773 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10774 rsurface.ent_skinnum = 0;
10775 rsurface.ent_qwskin = -1;
10776 rsurface.ent_shadertime = 0;
10777 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10778 if (rsurface.array_size < model->surfmesh.num_vertices)
10779 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10780 rsurface.matrix = identitymatrix;
10781 rsurface.inversematrix = identitymatrix;
10782 rsurface.matrixscale = 1;
10783 rsurface.inversematrixscale = 1;
10784 R_EntityMatrix(&identitymatrix);
10785 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10786 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10787 rsurface.fograngerecip = r_refdef.fograngerecip;
10788 rsurface.fogheightfade = r_refdef.fogheightfade;
10789 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10790 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10791 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10792 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10793 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10794 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10795 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10796 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10797 rsurface.colormod[3] = 1;
10798 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);
10799 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10800 rsurface.frameblend[0].lerp = 1;
10801 rsurface.ent_alttextures = false;
10802 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10803 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10804 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
10805 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10806 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10807 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10808 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10809 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10810 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10811 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10812 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10813 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
10814 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10815 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10816 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
10817 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10818 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10819 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
10820 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10821 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10822 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
10823 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10824 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10825 rsurface.modelelement3i = model->surfmesh.data_element3i;
10826 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10827 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10828 rsurface.modelelement3s = model->surfmesh.data_element3s;
10829 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10830 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10831 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10832 rsurface.modelnumvertices = model->surfmesh.num_vertices;
10833 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10834 rsurface.modelsurfaces = model->data_surfaces;
10835 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10836 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10837 rsurface.modelvertexposition = model->surfmesh.vertexposition;
10838 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10839 rsurface.modelgeneratedvertex = false;
10840 rsurface.batchgeneratedvertex = false;
10841 rsurface.batchfirstvertex = 0;
10842 rsurface.batchnumvertices = 0;
10843 rsurface.batchfirsttriangle = 0;
10844 rsurface.batchnumtriangles = 0;
10845 rsurface.batchvertex3f = NULL;
10846 rsurface.batchvertex3f_vertexbuffer = NULL;
10847 rsurface.batchvertex3f_bufferoffset = 0;
10848 rsurface.batchsvector3f = NULL;
10849 rsurface.batchsvector3f_vertexbuffer = NULL;
10850 rsurface.batchsvector3f_bufferoffset = 0;
10851 rsurface.batchtvector3f = NULL;
10852 rsurface.batchtvector3f_vertexbuffer = NULL;
10853 rsurface.batchtvector3f_bufferoffset = 0;
10854 rsurface.batchnormal3f = NULL;
10855 rsurface.batchnormal3f_vertexbuffer = NULL;
10856 rsurface.batchnormal3f_bufferoffset = 0;
10857 rsurface.batchlightmapcolor4f = NULL;
10858 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10859 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10860 rsurface.batchtexcoordtexture2f = NULL;
10861 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10862 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10863 rsurface.batchtexcoordlightmap2f = NULL;
10864 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10865 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10866 rsurface.batchvertexmesh = NULL;
10867 rsurface.batchvertexmeshbuffer = NULL;
10868 rsurface.batchvertexposition = NULL;
10869 rsurface.batchvertexpositionbuffer = NULL;
10870 rsurface.batchelement3i = NULL;
10871 rsurface.batchelement3i_indexbuffer = NULL;
10872 rsurface.batchelement3i_bufferoffset = 0;
10873 rsurface.batchelement3s = NULL;
10874 rsurface.batchelement3s_indexbuffer = NULL;
10875 rsurface.batchelement3s_bufferoffset = 0;
10876 rsurface.passcolor4f = NULL;
10877 rsurface.passcolor4f_vertexbuffer = NULL;
10878 rsurface.passcolor4f_bufferoffset = 0;
10881 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10883 dp_model_t *model = ent->model;
10884 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10886 rsurface.entity = (entity_render_t *)ent;
10887 rsurface.skeleton = ent->skeleton;
10888 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10889 rsurface.ent_skinnum = ent->skinnum;
10890 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;
10891 rsurface.ent_shadertime = ent->shadertime;
10892 rsurface.ent_flags = ent->flags;
10893 if (rsurface.array_size < model->surfmesh.num_vertices)
10894 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10895 rsurface.matrix = ent->matrix;
10896 rsurface.inversematrix = ent->inversematrix;
10897 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10898 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10899 R_EntityMatrix(&rsurface.matrix);
10900 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10901 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10902 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10903 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10904 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10905 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10906 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10907 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10908 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10909 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10910 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10911 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10912 rsurface.colormod[3] = ent->alpha;
10913 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10914 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10915 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10916 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10917 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10918 if (ent->model->brush.submodel && !prepass)
10920 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10921 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10923 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10925 if (ent->animcache_vertex3f && !r_framedata_failed)
10927 rsurface.modelvertex3f = ent->animcache_vertex3f;
10928 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10929 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10930 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10931 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
10932 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
10933 rsurface.modelvertexposition = ent->animcache_vertexposition;
10934 rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
10936 else if (wanttangents)
10938 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10939 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10940 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10941 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10942 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
10943 rsurface.modelvertexmesh = NULL;
10944 rsurface.modelvertexmeshbuffer = NULL;
10945 rsurface.modelvertexposition = NULL;
10946 rsurface.modelvertexpositionbuffer = NULL;
10948 else if (wantnormals)
10950 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10951 rsurface.modelsvector3f = NULL;
10952 rsurface.modeltvector3f = NULL;
10953 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10954 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
10955 rsurface.modelvertexmesh = NULL;
10956 rsurface.modelvertexmeshbuffer = NULL;
10957 rsurface.modelvertexposition = NULL;
10958 rsurface.modelvertexpositionbuffer = NULL;
10962 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10963 rsurface.modelsvector3f = NULL;
10964 rsurface.modeltvector3f = NULL;
10965 rsurface.modelnormal3f = NULL;
10966 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
10967 rsurface.modelvertexmesh = NULL;
10968 rsurface.modelvertexmeshbuffer = NULL;
10969 rsurface.modelvertexposition = NULL;
10970 rsurface.modelvertexpositionbuffer = NULL;
10972 rsurface.modelvertex3f_vertexbuffer = 0;
10973 rsurface.modelvertex3f_bufferoffset = 0;
10974 rsurface.modelsvector3f_vertexbuffer = 0;
10975 rsurface.modelsvector3f_bufferoffset = 0;
10976 rsurface.modeltvector3f_vertexbuffer = 0;
10977 rsurface.modeltvector3f_bufferoffset = 0;
10978 rsurface.modelnormal3f_vertexbuffer = 0;
10979 rsurface.modelnormal3f_bufferoffset = 0;
10980 rsurface.modelgeneratedvertex = true;
10984 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
10985 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10986 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10987 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10988 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10989 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10990 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10991 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10992 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10993 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
10994 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10995 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10996 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10997 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10998 rsurface.modelvertexposition = model->surfmesh.vertexposition;
10999 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
11000 rsurface.modelgeneratedvertex = false;
11002 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
11003 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11004 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11005 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
11006 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11007 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11008 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
11009 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11010 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11011 rsurface.modelelement3i = model->surfmesh.data_element3i;
11012 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11013 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11014 rsurface.modelelement3s = model->surfmesh.data_element3s;
11015 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11016 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11017 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11018 rsurface.modelnumvertices = model->surfmesh.num_vertices;
11019 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11020 rsurface.modelsurfaces = model->data_surfaces;
11021 rsurface.batchgeneratedvertex = false;
11022 rsurface.batchfirstvertex = 0;
11023 rsurface.batchnumvertices = 0;
11024 rsurface.batchfirsttriangle = 0;
11025 rsurface.batchnumtriangles = 0;
11026 rsurface.batchvertex3f = NULL;
11027 rsurface.batchvertex3f_vertexbuffer = NULL;
11028 rsurface.batchvertex3f_bufferoffset = 0;
11029 rsurface.batchsvector3f = NULL;
11030 rsurface.batchsvector3f_vertexbuffer = NULL;
11031 rsurface.batchsvector3f_bufferoffset = 0;
11032 rsurface.batchtvector3f = NULL;
11033 rsurface.batchtvector3f_vertexbuffer = NULL;
11034 rsurface.batchtvector3f_bufferoffset = 0;
11035 rsurface.batchnormal3f = NULL;
11036 rsurface.batchnormal3f_vertexbuffer = NULL;
11037 rsurface.batchnormal3f_bufferoffset = 0;
11038 rsurface.batchlightmapcolor4f = NULL;
11039 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11040 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11041 rsurface.batchtexcoordtexture2f = NULL;
11042 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11043 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11044 rsurface.batchtexcoordlightmap2f = NULL;
11045 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11046 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11047 rsurface.batchvertexmesh = NULL;
11048 rsurface.batchvertexmeshbuffer = NULL;
11049 rsurface.batchvertexposition = NULL;
11050 rsurface.batchvertexpositionbuffer = NULL;
11051 rsurface.batchelement3i = NULL;
11052 rsurface.batchelement3i_indexbuffer = NULL;
11053 rsurface.batchelement3i_bufferoffset = 0;
11054 rsurface.batchelement3s = NULL;
11055 rsurface.batchelement3s_indexbuffer = NULL;
11056 rsurface.batchelement3s_bufferoffset = 0;
11057 rsurface.passcolor4f = NULL;
11058 rsurface.passcolor4f_vertexbuffer = NULL;
11059 rsurface.passcolor4f_bufferoffset = 0;
11062 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)
11066 rsurface.entity = r_refdef.scene.worldentity;
11067 rsurface.skeleton = NULL;
11068 rsurface.ent_skinnum = 0;
11069 rsurface.ent_qwskin = -1;
11070 rsurface.ent_shadertime = shadertime;
11071 rsurface.ent_flags = entflags;
11072 rsurface.modelnumvertices = numvertices;
11073 rsurface.modelnumtriangles = numtriangles;
11074 if (rsurface.array_size < rsurface.modelnumvertices)
11075 R_Mesh_ResizeArrays(rsurface.modelnumvertices);
11076 rsurface.matrix = *matrix;
11077 rsurface.inversematrix = *inversematrix;
11078 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11079 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11080 R_EntityMatrix(&rsurface.matrix);
11081 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11082 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11083 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11084 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11085 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11086 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11087 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11088 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11089 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11090 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11091 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11092 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
11093 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);
11094 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11095 rsurface.frameblend[0].lerp = 1;
11096 rsurface.ent_alttextures = false;
11097 rsurface.basepolygonfactor = r_refdef.polygonfactor;
11098 rsurface.basepolygonoffset = r_refdef.polygonoffset;
11101 rsurface.modelvertex3f = vertex3f;
11102 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
11103 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
11104 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11106 else if (wantnormals)
11108 rsurface.modelvertex3f = vertex3f;
11109 rsurface.modelsvector3f = NULL;
11110 rsurface.modeltvector3f = NULL;
11111 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11115 rsurface.modelvertex3f = vertex3f;
11116 rsurface.modelsvector3f = NULL;
11117 rsurface.modeltvector3f = NULL;
11118 rsurface.modelnormal3f = NULL;
11120 rsurface.modelvertexmesh = NULL;
11121 rsurface.modelvertexmeshbuffer = NULL;
11122 rsurface.modelvertexposition = NULL;
11123 rsurface.modelvertexpositionbuffer = NULL;
11124 rsurface.modelvertex3f_vertexbuffer = 0;
11125 rsurface.modelvertex3f_bufferoffset = 0;
11126 rsurface.modelsvector3f_vertexbuffer = 0;
11127 rsurface.modelsvector3f_bufferoffset = 0;
11128 rsurface.modeltvector3f_vertexbuffer = 0;
11129 rsurface.modeltvector3f_bufferoffset = 0;
11130 rsurface.modelnormal3f_vertexbuffer = 0;
11131 rsurface.modelnormal3f_bufferoffset = 0;
11132 rsurface.modelgeneratedvertex = true;
11133 rsurface.modellightmapcolor4f = color4f;
11134 rsurface.modellightmapcolor4f_vertexbuffer = 0;
11135 rsurface.modellightmapcolor4f_bufferoffset = 0;
11136 rsurface.modeltexcoordtexture2f = texcoord2f;
11137 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
11138 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
11139 rsurface.modeltexcoordlightmap2f = NULL;
11140 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
11141 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
11142 rsurface.modelelement3i = element3i;
11143 rsurface.modelelement3i_indexbuffer = NULL;
11144 rsurface.modelelement3i_bufferoffset = 0;
11145 rsurface.modelelement3s = element3s;
11146 rsurface.modelelement3s_indexbuffer = NULL;
11147 rsurface.modelelement3s_bufferoffset = 0;
11148 rsurface.modellightmapoffsets = NULL;
11149 rsurface.modelsurfaces = NULL;
11150 rsurface.batchgeneratedvertex = false;
11151 rsurface.batchfirstvertex = 0;
11152 rsurface.batchnumvertices = 0;
11153 rsurface.batchfirsttriangle = 0;
11154 rsurface.batchnumtriangles = 0;
11155 rsurface.batchvertex3f = NULL;
11156 rsurface.batchvertex3f_vertexbuffer = NULL;
11157 rsurface.batchvertex3f_bufferoffset = 0;
11158 rsurface.batchsvector3f = NULL;
11159 rsurface.batchsvector3f_vertexbuffer = NULL;
11160 rsurface.batchsvector3f_bufferoffset = 0;
11161 rsurface.batchtvector3f = NULL;
11162 rsurface.batchtvector3f_vertexbuffer = NULL;
11163 rsurface.batchtvector3f_bufferoffset = 0;
11164 rsurface.batchnormal3f = NULL;
11165 rsurface.batchnormal3f_vertexbuffer = NULL;
11166 rsurface.batchnormal3f_bufferoffset = 0;
11167 rsurface.batchlightmapcolor4f = NULL;
11168 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11169 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11170 rsurface.batchtexcoordtexture2f = NULL;
11171 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11172 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11173 rsurface.batchtexcoordlightmap2f = NULL;
11174 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11175 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11176 rsurface.batchvertexmesh = NULL;
11177 rsurface.batchvertexmeshbuffer = NULL;
11178 rsurface.batchvertexposition = NULL;
11179 rsurface.batchvertexpositionbuffer = NULL;
11180 rsurface.batchelement3i = NULL;
11181 rsurface.batchelement3i_indexbuffer = NULL;
11182 rsurface.batchelement3i_bufferoffset = 0;
11183 rsurface.batchelement3s = NULL;
11184 rsurface.batchelement3s_indexbuffer = NULL;
11185 rsurface.batchelement3s_bufferoffset = 0;
11186 rsurface.passcolor4f = NULL;
11187 rsurface.passcolor4f_vertexbuffer = NULL;
11188 rsurface.passcolor4f_bufferoffset = 0;
11190 if (rsurface.modelnumvertices && rsurface.modelelement3i)
11192 if ((wantnormals || wanttangents) && !normal3f)
11194 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
11195 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11197 if (wanttangents && !svector3f)
11199 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);
11200 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11201 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11205 // now convert arrays into vertexmesh structs
11206 for (i = 0;i < numvertices;i++)
11208 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexposition[i].vertex3f);
11209 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexmesh[i].vertex3f);
11210 if (rsurface.modelsvector3f)
11211 VectorCopy(rsurface.modelsvector3f + 3*i, rsurface.array_modelvertexmesh[i].svector3f);
11212 if (rsurface.modeltvector3f)
11213 VectorCopy(rsurface.modeltvector3f + 3*i, rsurface.array_modelvertexmesh[i].tvector3f);
11214 if (rsurface.modelnormal3f)
11215 VectorCopy(rsurface.modelnormal3f + 3*i, rsurface.array_modelvertexmesh[i].normal3f);
11216 if (rsurface.modellightmapcolor4f)
11217 Vector4Scale(rsurface.modellightmapcolor4f + 4*i, 255.0f, rsurface.array_modelvertexmesh[i].color4ub);
11218 if (rsurface.modeltexcoordtexture2f)
11219 Vector2Copy(rsurface.modeltexcoordtexture2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordtexture2f);
11220 if (rsurface.modeltexcoordlightmap2f)
11221 Vector2Copy(rsurface.modeltexcoordlightmap2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordlightmap2f);
11225 float RSurf_FogPoint(const float *v)
11227 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11228 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11229 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11230 float FogHeightFade = r_refdef.fogheightfade;
11232 unsigned int fogmasktableindex;
11233 if (r_refdef.fogplaneviewabove)
11234 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11236 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11237 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11238 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11241 float RSurf_FogVertex(const float *v)
11243 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11244 float FogPlaneViewDist = rsurface.fogplaneviewdist;
11245 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11246 float FogHeightFade = rsurface.fogheightfade;
11248 unsigned int fogmasktableindex;
11249 if (r_refdef.fogplaneviewabove)
11250 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11252 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11253 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11254 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11257 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11260 for (i = 0;i < numelements;i++)
11261 outelement3i[i] = inelement3i[i] + adjust;
11264 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11265 extern cvar_t gl_vbo;
11266 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11274 int surfacefirsttriangle;
11275 int surfacenumtriangles;
11276 int surfacefirstvertex;
11277 int surfaceendvertex;
11278 int surfacenumvertices;
11282 qboolean dynamicvertex;
11286 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11287 float waveparms[4];
11288 q3shaderinfo_deform_t *deform;
11289 const msurface_t *surface, *firstsurface;
11290 r_vertexposition_t *vertexposition;
11291 r_vertexmesh_t *vertexmesh;
11292 if (!texturenumsurfaces)
11294 // find vertex range of this surface batch
11296 firstsurface = texturesurfacelist[0];
11297 firsttriangle = firstsurface->num_firsttriangle;
11299 firstvertex = endvertex = firstsurface->num_firstvertex;
11300 for (i = 0;i < texturenumsurfaces;i++)
11302 surface = texturesurfacelist[i];
11303 if (surface != firstsurface + i)
11305 surfacefirstvertex = surface->num_firstvertex;
11306 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11307 surfacenumtriangles = surface->num_triangles;
11308 if (firstvertex > surfacefirstvertex)
11309 firstvertex = surfacefirstvertex;
11310 if (endvertex < surfaceendvertex)
11311 endvertex = surfaceendvertex;
11312 numtriangles += surfacenumtriangles;
11317 // we now know the vertex range used, and if there are any gaps in it
11318 rsurface.batchfirstvertex = firstvertex;
11319 rsurface.batchnumvertices = endvertex - firstvertex;
11320 rsurface.batchfirsttriangle = firsttriangle;
11321 rsurface.batchnumtriangles = numtriangles;
11323 // this variable holds flags for which properties have been updated that
11324 // may require regenerating vertexmesh or vertexposition arrays...
11327 // check if any dynamic vertex processing must occur
11328 dynamicvertex = false;
11330 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11331 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
11332 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11334 switch (deform->deform)
11337 case Q3DEFORM_PROJECTIONSHADOW:
11338 case Q3DEFORM_TEXT0:
11339 case Q3DEFORM_TEXT1:
11340 case Q3DEFORM_TEXT2:
11341 case Q3DEFORM_TEXT3:
11342 case Q3DEFORM_TEXT4:
11343 case Q3DEFORM_TEXT5:
11344 case Q3DEFORM_TEXT6:
11345 case Q3DEFORM_TEXT7:
11346 case Q3DEFORM_NONE:
11348 case Q3DEFORM_AUTOSPRITE:
11349 dynamicvertex = true;
11350 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11351 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11353 case Q3DEFORM_AUTOSPRITE2:
11354 dynamicvertex = true;
11355 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11356 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11358 case Q3DEFORM_NORMAL:
11359 dynamicvertex = true;
11360 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11361 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11363 case Q3DEFORM_WAVE:
11364 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11365 break; // if wavefunc is a nop, ignore this transform
11366 dynamicvertex = true;
11367 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11368 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11370 case Q3DEFORM_BULGE:
11371 dynamicvertex = true;
11372 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11373 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11375 case Q3DEFORM_MOVE:
11376 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11377 break; // if wavefunc is a nop, ignore this transform
11378 dynamicvertex = true;
11379 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11380 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
11384 switch(rsurface.texture->tcgen.tcgen)
11387 case Q3TCGEN_TEXTURE:
11389 case Q3TCGEN_LIGHTMAP:
11390 dynamicvertex = true;
11391 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11392 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11394 case Q3TCGEN_VECTOR:
11395 dynamicvertex = true;
11396 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11397 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11399 case Q3TCGEN_ENVIRONMENT:
11400 dynamicvertex = true;
11401 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11402 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11405 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11407 dynamicvertex = true;
11408 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11409 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11412 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11414 dynamicvertex = true;
11415 batchneed |= BATCHNEED_NOGAPS;
11416 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11419 if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11421 dynamicvertex = true;
11422 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11423 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
11426 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11428 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11429 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
11430 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
11431 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
11432 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11433 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11434 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11437 // when the model data has no vertex buffer (dynamic mesh), we need to
11439 if (!rsurface.modelvertexmeshbuffer)
11440 batchneed |= BATCHNEED_NOGAPS;
11442 // if needsupdate, we have to do a dynamic vertex batch for sure
11443 if (needsupdate & batchneed)
11444 dynamicvertex = true;
11446 // see if we need to build vertexmesh from arrays
11447 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11448 dynamicvertex = true;
11450 // see if we need to build vertexposition from arrays
11451 if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
11452 dynamicvertex = true;
11454 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11455 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11456 dynamicvertex = true;
11458 // if there is a chance of animated vertex colors, it's a dynamic batch
11459 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11460 dynamicvertex = true;
11462 rsurface.batchvertex3f = rsurface.modelvertex3f;
11463 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11464 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11465 rsurface.batchsvector3f = rsurface.modelsvector3f;
11466 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11467 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11468 rsurface.batchtvector3f = rsurface.modeltvector3f;
11469 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11470 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11471 rsurface.batchnormal3f = rsurface.modelnormal3f;
11472 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11473 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11474 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11475 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
11476 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11477 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11478 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
11479 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
11480 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11481 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11482 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11483 rsurface.batchvertexposition = rsurface.modelvertexposition;
11484 rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
11485 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11486 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11487 rsurface.batchelement3i = rsurface.modelelement3i;
11488 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11489 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11490 rsurface.batchelement3s = rsurface.modelelement3s;
11491 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11492 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11494 // if any dynamic vertex processing has to occur in software, we copy the
11495 // entire surface list together before processing to rebase the vertices
11496 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11498 // if any gaps exist and we do not have a static vertex buffer, we have to
11499 // copy the surface list together to avoid wasting upload bandwidth on the
11500 // vertices in the gaps.
11502 // if gaps exist and we have a static vertex buffer, we still have to
11503 // combine the index buffer ranges into one dynamic index buffer.
11505 // in all cases we end up with data that can be drawn in one call.
11507 if (!dynamicvertex)
11509 // static vertex data, just set pointers...
11510 rsurface.batchgeneratedvertex = false;
11511 // if there are gaps, we want to build a combined index buffer,
11512 // otherwise use the original static buffer with an appropriate offset
11517 for (i = 0;i < texturenumsurfaces;i++)
11519 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11520 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11521 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11522 numtriangles += surfacenumtriangles;
11524 rsurface.batchelement3i = rsurface.array_batchelement3i;
11525 rsurface.batchelement3i_indexbuffer = NULL;
11526 rsurface.batchelement3i_bufferoffset = 0;
11527 rsurface.batchelement3s = NULL;
11528 rsurface.batchelement3s_indexbuffer = NULL;
11529 rsurface.batchelement3s_bufferoffset = 0;
11530 if (endvertex <= 65536)
11532 rsurface.batchelement3s = rsurface.array_batchelement3s;
11533 for (i = 0;i < numtriangles*3;i++)
11534 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11536 rsurface.batchfirsttriangle = firsttriangle;
11537 rsurface.batchnumtriangles = numtriangles;
11542 // something needs software processing, do it for real...
11543 // we only directly handle interleaved array data in this case...
11544 rsurface.batchgeneratedvertex = true;
11546 // now copy the vertex data into a combined array and make an index array
11547 // (this is what Quake3 does all the time)
11548 //if (gaps || rsurface.batchfirstvertex)
11550 rsurface.batchvertexposition = NULL;
11551 rsurface.batchvertexpositionbuffer = NULL;
11552 rsurface.batchvertexmesh = NULL;
11553 rsurface.batchvertexmeshbuffer = NULL;
11554 rsurface.batchvertex3f = NULL;
11555 rsurface.batchvertex3f_vertexbuffer = NULL;
11556 rsurface.batchvertex3f_bufferoffset = 0;
11557 rsurface.batchsvector3f = NULL;
11558 rsurface.batchsvector3f_vertexbuffer = NULL;
11559 rsurface.batchsvector3f_bufferoffset = 0;
11560 rsurface.batchtvector3f = NULL;
11561 rsurface.batchtvector3f_vertexbuffer = NULL;
11562 rsurface.batchtvector3f_bufferoffset = 0;
11563 rsurface.batchnormal3f = NULL;
11564 rsurface.batchnormal3f_vertexbuffer = NULL;
11565 rsurface.batchnormal3f_bufferoffset = 0;
11566 rsurface.batchlightmapcolor4f = NULL;
11567 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11568 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11569 rsurface.batchtexcoordtexture2f = NULL;
11570 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11571 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11572 rsurface.batchtexcoordlightmap2f = NULL;
11573 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11574 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11575 rsurface.batchelement3i = rsurface.array_batchelement3i;
11576 rsurface.batchelement3i_indexbuffer = NULL;
11577 rsurface.batchelement3i_bufferoffset = 0;
11578 rsurface.batchelement3s = NULL;
11579 rsurface.batchelement3s_indexbuffer = NULL;
11580 rsurface.batchelement3s_bufferoffset = 0;
11581 // we'll only be setting up certain arrays as needed
11582 if (batchneed & BATCHNEED_VERTEXPOSITION)
11583 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11584 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11585 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11586 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11587 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11588 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11589 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11590 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11592 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11593 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11595 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11596 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11597 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11598 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11599 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11600 rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
11603 for (i = 0;i < texturenumsurfaces;i++)
11605 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11606 surfacenumvertices = texturesurfacelist[i]->num_vertices;
11607 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11608 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11609 // copy only the data requested
11610 if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
11611 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
11612 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11613 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11614 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11616 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11617 memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11618 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11619 memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11620 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11622 memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11623 memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11625 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11626 memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11627 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11628 memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11629 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11630 memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11632 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11633 numvertices += surfacenumvertices;
11634 numtriangles += surfacenumtriangles;
11637 // generate a 16bit index array as well if possible
11638 // (in general, dynamic batches fit)
11639 if (numvertices <= 65536)
11641 rsurface.batchelement3s = rsurface.array_batchelement3s;
11642 for (i = 0;i < numtriangles*3;i++)
11643 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11646 // since we've copied everything, the batch now starts at 0
11647 rsurface.batchfirstvertex = 0;
11648 rsurface.batchnumvertices = numvertices;
11649 rsurface.batchfirsttriangle = 0;
11650 rsurface.batchnumtriangles = numtriangles;
11653 // q1bsp surfaces rendered in vertex color mode have to have colors
11654 // calculated based on lightstyles
11655 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11657 // generate color arrays for the surfaces in this list
11661 const int *offsets;
11662 const unsigned char *lm;
11664 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11665 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11666 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11667 for (i = 0;i < texturenumsurfaces;i++)
11669 surface = texturesurfacelist[i];
11670 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11671 surfacenumvertices = surface->num_vertices;
11672 if (surface->lightmapinfo->samples)
11674 for (j = 0;j < surfacenumvertices;j++)
11676 lm = surface->lightmapinfo->samples + offsets[j];
11677 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11678 VectorScale(lm, scale, c);
11679 if (surface->lightmapinfo->styles[1] != 255)
11681 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11683 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11684 VectorMA(c, scale, lm, c);
11685 if (surface->lightmapinfo->styles[2] != 255)
11688 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11689 VectorMA(c, scale, lm, c);
11690 if (surface->lightmapinfo->styles[3] != 255)
11693 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11694 VectorMA(c, scale, lm, c);
11701 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);
11707 for (j = 0;j < surfacenumvertices;j++)
11709 Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11716 // if vertices are deformed (sprite flares and things in maps, possibly
11717 // water waves, bulges and other deformations), modify the copied vertices
11719 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11721 switch (deform->deform)
11724 case Q3DEFORM_PROJECTIONSHADOW:
11725 case Q3DEFORM_TEXT0:
11726 case Q3DEFORM_TEXT1:
11727 case Q3DEFORM_TEXT2:
11728 case Q3DEFORM_TEXT3:
11729 case Q3DEFORM_TEXT4:
11730 case Q3DEFORM_TEXT5:
11731 case Q3DEFORM_TEXT6:
11732 case Q3DEFORM_TEXT7:
11733 case Q3DEFORM_NONE:
11735 case Q3DEFORM_AUTOSPRITE:
11736 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11737 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11738 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11739 VectorNormalize(newforward);
11740 VectorNormalize(newright);
11741 VectorNormalize(newup);
11742 // a single autosprite surface can contain multiple sprites...
11743 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11745 VectorClear(center);
11746 for (i = 0;i < 4;i++)
11747 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11748 VectorScale(center, 0.25f, center);
11749 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11750 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11751 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11752 for (i = 0;i < 4;i++)
11754 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11755 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
11758 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11759 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11760 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);
11761 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11762 rsurface.batchvertex3f_vertexbuffer = NULL;
11763 rsurface.batchvertex3f_bufferoffset = 0;
11764 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11765 rsurface.batchsvector3f_vertexbuffer = NULL;
11766 rsurface.batchsvector3f_bufferoffset = 0;
11767 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11768 rsurface.batchtvector3f_vertexbuffer = NULL;
11769 rsurface.batchtvector3f_bufferoffset = 0;
11770 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11771 rsurface.batchnormal3f_vertexbuffer = NULL;
11772 rsurface.batchnormal3f_bufferoffset = 0;
11774 case Q3DEFORM_AUTOSPRITE2:
11775 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11776 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11777 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11778 VectorNormalize(newforward);
11779 VectorNormalize(newright);
11780 VectorNormalize(newup);
11782 const float *v1, *v2;
11792 memset(shortest, 0, sizeof(shortest));
11793 // a single autosprite surface can contain multiple sprites...
11794 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11796 VectorClear(center);
11797 for (i = 0;i < 4;i++)
11798 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11799 VectorScale(center, 0.25f, center);
11800 // find the two shortest edges, then use them to define the
11801 // axis vectors for rotating around the central axis
11802 for (i = 0;i < 6;i++)
11804 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11805 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11806 l = VectorDistance2(v1, v2);
11807 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11808 if (v1[2] != v2[2])
11809 l += (1.0f / 1024.0f);
11810 if (shortest[0].length2 > l || i == 0)
11812 shortest[1] = shortest[0];
11813 shortest[0].length2 = l;
11814 shortest[0].v1 = v1;
11815 shortest[0].v2 = v2;
11817 else if (shortest[1].length2 > l || i == 1)
11819 shortest[1].length2 = l;
11820 shortest[1].v1 = v1;
11821 shortest[1].v2 = v2;
11824 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11825 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11826 // this calculates the right vector from the shortest edge
11827 // and the up vector from the edge midpoints
11828 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11829 VectorNormalize(right);
11830 VectorSubtract(end, start, up);
11831 VectorNormalize(up);
11832 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11833 VectorSubtract(rsurface.localvieworigin, center, forward);
11834 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11835 VectorNegate(forward, forward);
11836 VectorReflect(forward, 0, up, forward);
11837 VectorNormalize(forward);
11838 CrossProduct(up, forward, newright);
11839 VectorNormalize(newright);
11840 // rotate the quad around the up axis vector, this is made
11841 // especially easy by the fact we know the quad is flat,
11842 // so we only have to subtract the center position and
11843 // measure distance along the right vector, and then
11844 // multiply that by the newright vector and add back the
11846 // we also need to subtract the old position to undo the
11847 // displacement from the center, which we do with a
11848 // DotProduct, the subtraction/addition of center is also
11849 // optimized into DotProducts here
11850 l = DotProduct(right, center);
11851 for (i = 0;i < 4;i++)
11853 v1 = rsurface.batchvertex3f + 3*(j+i);
11854 f = DotProduct(right, v1) - l;
11855 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
11859 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11860 rsurface.batchvertex3f_vertexbuffer = NULL;
11861 rsurface.batchvertex3f_bufferoffset = 0;
11862 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11864 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11865 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11866 rsurface.batchnormal3f_vertexbuffer = NULL;
11867 rsurface.batchnormal3f_bufferoffset = 0;
11869 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11871 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);
11872 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11873 rsurface.batchsvector3f_vertexbuffer = NULL;
11874 rsurface.batchsvector3f_bufferoffset = 0;
11875 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11876 rsurface.batchtvector3f_vertexbuffer = NULL;
11877 rsurface.batchtvector3f_bufferoffset = 0;
11880 case Q3DEFORM_NORMAL:
11881 // deform the normals to make reflections wavey
11882 for (j = 0;j < rsurface.batchnumvertices;j++)
11885 float *normal = rsurface.array_batchnormal3f + 3*j;
11886 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11887 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11888 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]);
11889 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]);
11890 VectorNormalize(normal);
11892 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11893 rsurface.batchnormal3f_vertexbuffer = NULL;
11894 rsurface.batchnormal3f_bufferoffset = 0;
11895 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11897 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);
11898 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11899 rsurface.batchsvector3f_vertexbuffer = NULL;
11900 rsurface.batchsvector3f_bufferoffset = 0;
11901 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11902 rsurface.batchtvector3f_vertexbuffer = NULL;
11903 rsurface.batchtvector3f_bufferoffset = 0;
11906 case Q3DEFORM_WAVE:
11907 // deform vertex array to make wavey water and flags and such
11908 waveparms[0] = deform->waveparms[0];
11909 waveparms[1] = deform->waveparms[1];
11910 waveparms[2] = deform->waveparms[2];
11911 waveparms[3] = deform->waveparms[3];
11912 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11913 break; // if wavefunc is a nop, don't make a dynamic vertex array
11914 // this is how a divisor of vertex influence on deformation
11915 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11916 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11917 for (j = 0;j < rsurface.batchnumvertices;j++)
11919 // if the wavefunc depends on time, evaluate it per-vertex
11922 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11923 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11925 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11927 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11928 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11929 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11930 rsurface.batchvertex3f_vertexbuffer = NULL;
11931 rsurface.batchvertex3f_bufferoffset = 0;
11932 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11933 rsurface.batchnormal3f_vertexbuffer = NULL;
11934 rsurface.batchnormal3f_bufferoffset = 0;
11935 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11937 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);
11938 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11939 rsurface.batchsvector3f_vertexbuffer = NULL;
11940 rsurface.batchsvector3f_bufferoffset = 0;
11941 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11942 rsurface.batchtvector3f_vertexbuffer = NULL;
11943 rsurface.batchtvector3f_bufferoffset = 0;
11946 case Q3DEFORM_BULGE:
11947 // deform vertex array to make the surface have moving bulges
11948 for (j = 0;j < rsurface.batchnumvertices;j++)
11950 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
11951 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11953 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11954 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11955 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11956 rsurface.batchvertex3f_vertexbuffer = NULL;
11957 rsurface.batchvertex3f_bufferoffset = 0;
11958 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11959 rsurface.batchnormal3f_vertexbuffer = NULL;
11960 rsurface.batchnormal3f_bufferoffset = 0;
11961 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11963 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);
11964 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11965 rsurface.batchsvector3f_vertexbuffer = NULL;
11966 rsurface.batchsvector3f_bufferoffset = 0;
11967 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11968 rsurface.batchtvector3f_vertexbuffer = NULL;
11969 rsurface.batchtvector3f_bufferoffset = 0;
11972 case Q3DEFORM_MOVE:
11973 // deform vertex array
11974 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11975 break; // if wavefunc is a nop, don't make a dynamic vertex array
11976 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
11977 VectorScale(deform->parms, scale, waveparms);
11978 for (j = 0;j < rsurface.batchnumvertices;j++)
11979 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
11980 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11981 rsurface.batchvertex3f_vertexbuffer = NULL;
11982 rsurface.batchvertex3f_bufferoffset = 0;
11987 // generate texcoords based on the chosen texcoord source
11988 switch(rsurface.texture->tcgen.tcgen)
11991 case Q3TCGEN_TEXTURE:
11993 case Q3TCGEN_LIGHTMAP:
11994 if (rsurface.batchtexcoordlightmap2f)
11995 memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
11996 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11997 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11998 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12000 case Q3TCGEN_VECTOR:
12001 for (j = 0;j < rsurface.batchnumvertices;j++)
12003 rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
12004 rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
12006 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12007 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12008 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12010 case Q3TCGEN_ENVIRONMENT:
12011 // make environment reflections using a spheremap
12012 for (j = 0;j < rsurface.batchnumvertices;j++)
12014 // identical to Q3A's method, but executed in worldspace so
12015 // carried models can be shiny too
12017 float viewer[3], d, reflected[3], worldreflected[3];
12019 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
12020 // VectorNormalize(viewer);
12022 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
12024 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
12025 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
12026 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
12027 // note: this is proportinal to viewer, so we can normalize later
12029 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
12030 VectorNormalize(worldreflected);
12032 // note: this sphere map only uses world x and z!
12033 // so positive and negative y will LOOK THE SAME.
12034 rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
12035 rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
12037 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12038 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12039 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12042 // the only tcmod that needs software vertex processing is turbulent, so
12043 // check for it here and apply the changes if needed
12044 // and we only support that as the first one
12045 // (handling a mixture of turbulent and other tcmods would be problematic
12046 // without punting it entirely to a software path)
12047 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
12049 amplitude = rsurface.texture->tcmods[0].parms[1];
12050 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
12051 for (j = 0;j < rsurface.batchnumvertices;j++)
12053 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);
12054 rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12056 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12057 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12058 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12061 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
12063 // convert the modified arrays to vertex structs
12064 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
12065 rsurface.batchvertexmeshbuffer = NULL;
12066 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
12067 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12068 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
12069 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
12070 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12071 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
12072 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
12074 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12076 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
12077 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
12080 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
12081 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12082 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
12083 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
12084 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12085 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
12086 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
12087 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12088 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
12091 if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
12093 // convert the modified arrays to vertex structs
12094 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
12095 rsurface.batchvertexpositionbuffer = NULL;
12096 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
12097 memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
12099 for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
12100 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
12104 void RSurf_DrawBatch(void)
12106 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);
12109 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
12111 // pick the closest matching water plane
12112 int planeindex, vertexindex, bestplaneindex = -1;
12116 r_waterstate_waterplane_t *p;
12118 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
12120 if(p->camera_entity != rsurface.texture->camera_entity)
12123 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
12124 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
12126 Matrix4x4_Transform(&rsurface.matrix, v, vert);
12127 d += fabs(PlaneDiff(vert, &p->plane));
12129 if (bestd > d || bestplaneindex < 0)
12132 bestplaneindex = planeindex;
12135 return bestplaneindex;
12138 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
12141 for (i = 0;i < rsurface.batchnumvertices;i++)
12142 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
12143 rsurface.passcolor4f = rsurface.array_passcolor4f;
12144 rsurface.passcolor4f_vertexbuffer = 0;
12145 rsurface.passcolor4f_bufferoffset = 0;
12148 static void RSurf_DrawBatch_GL11_ApplyFog(void)
12155 if (rsurface.passcolor4f)
12157 // generate color arrays
12158 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)
12160 f = RSurf_FogVertex(v);
12169 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
12171 f = RSurf_FogVertex(v);
12178 rsurface.passcolor4f = rsurface.array_passcolor4f;
12179 rsurface.passcolor4f_vertexbuffer = 0;
12180 rsurface.passcolor4f_bufferoffset = 0;
12183 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
12190 if (!rsurface.passcolor4f)
12192 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)
12194 f = RSurf_FogVertex(v);
12195 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
12196 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
12197 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
12200 rsurface.passcolor4f = rsurface.array_passcolor4f;
12201 rsurface.passcolor4f_vertexbuffer = 0;
12202 rsurface.passcolor4f_bufferoffset = 0;
12205 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
12210 if (!rsurface.passcolor4f)
12212 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 rsurface.passcolor4f = rsurface.array_passcolor4f;
12220 rsurface.passcolor4f_vertexbuffer = 0;
12221 rsurface.passcolor4f_bufferoffset = 0;
12224 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12229 if (!rsurface.passcolor4f)
12231 for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12233 c2[0] = c[0] + r_refdef.scene.ambient;
12234 c2[1] = c[1] + r_refdef.scene.ambient;
12235 c2[2] = c[2] + r_refdef.scene.ambient;
12238 rsurface.passcolor4f = rsurface.array_passcolor4f;
12239 rsurface.passcolor4f_vertexbuffer = 0;
12240 rsurface.passcolor4f_bufferoffset = 0;
12243 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12246 rsurface.passcolor4f = NULL;
12247 rsurface.passcolor4f_vertexbuffer = 0;
12248 rsurface.passcolor4f_bufferoffset = 0;
12249 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12250 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12251 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12252 GL_Color(r, g, b, a);
12253 R_Mesh_TexBind(0, rsurface.lightmaptexture);
12257 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12259 // TODO: optimize applyfog && applycolor case
12260 // just apply fog if necessary, and tint the fog color array if necessary
12261 rsurface.passcolor4f = NULL;
12262 rsurface.passcolor4f_vertexbuffer = 0;
12263 rsurface.passcolor4f_bufferoffset = 0;
12264 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12265 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12266 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12267 GL_Color(r, g, b, a);
12271 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12274 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12275 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12276 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12277 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12278 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12279 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12280 GL_Color(r, g, b, a);
12284 static void RSurf_DrawBatch_GL11_ClampColor(void)
12289 if (!rsurface.passcolor4f)
12291 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12293 c2[0] = bound(0.0f, c1[0], 1.0f);
12294 c2[1] = bound(0.0f, c1[1], 1.0f);
12295 c2[2] = bound(0.0f, c1[2], 1.0f);
12296 c2[3] = bound(0.0f, c1[3], 1.0f);
12300 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
12310 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)
12312 f = -DotProduct(r_refdef.view.forward, n);
12314 f = f * 0.85 + 0.15; // work around so stuff won't get black
12315 f *= r_refdef.lightmapintensity;
12316 Vector4Set(c, f, f, f, 1);
12319 rsurface.passcolor4f = rsurface.array_passcolor4f;
12320 rsurface.passcolor4f_vertexbuffer = 0;
12321 rsurface.passcolor4f_bufferoffset = 0;
12324 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12326 RSurf_DrawBatch_GL11_ApplyFakeLight();
12327 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12328 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12329 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12330 GL_Color(r, g, b, a);
12334 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12342 vec3_t ambientcolor;
12343 vec3_t diffusecolor;
12347 VectorCopy(rsurface.modellight_lightdir, lightdir);
12348 f = 0.5f * r_refdef.lightmapintensity;
12349 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12350 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12351 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12352 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12353 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12354 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12356 if (VectorLength2(diffusecolor) > 0)
12358 // q3-style directional shading
12359 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)
12361 if ((f = DotProduct(n, lightdir)) > 0)
12362 VectorMA(ambientcolor, f, diffusecolor, c);
12364 VectorCopy(ambientcolor, c);
12371 rsurface.passcolor4f = rsurface.array_passcolor4f;
12372 rsurface.passcolor4f_vertexbuffer = 0;
12373 rsurface.passcolor4f_bufferoffset = 0;
12374 *applycolor = false;
12378 *r = ambientcolor[0];
12379 *g = ambientcolor[1];
12380 *b = ambientcolor[2];
12381 rsurface.passcolor4f = NULL;
12382 rsurface.passcolor4f_vertexbuffer = 0;
12383 rsurface.passcolor4f_bufferoffset = 0;
12387 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12389 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12390 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12391 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12392 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12393 GL_Color(r, g, b, a);
12397 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12403 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12405 f = 1 - RSurf_FogVertex(v);
12413 void RSurf_SetupDepthAndCulling(void)
12415 // submodels are biased to avoid z-fighting with world surfaces that they
12416 // may be exactly overlapping (avoids z-fighting artifacts on certain
12417 // doors and things in Quake maps)
12418 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12419 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12420 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12421 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12424 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12426 // transparent sky would be ridiculous
12427 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12429 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12430 skyrenderlater = true;
12431 RSurf_SetupDepthAndCulling();
12432 GL_DepthMask(true);
12433 // LordHavoc: HalfLife maps have freaky skypolys so don't use
12434 // skymasking on them, and Quake3 never did sky masking (unlike
12435 // software Quake and software Quake2), so disable the sky masking
12436 // in Quake3 maps as it causes problems with q3map2 sky tricks,
12437 // and skymasking also looks very bad when noclipping outside the
12438 // level, so don't use it then either.
12439 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12441 R_Mesh_ResetTextureState();
12442 if (skyrendermasked)
12444 R_SetupShader_DepthOrShadow();
12445 // depth-only (masking)
12446 GL_ColorMask(0,0,0,0);
12447 // just to make sure that braindead drivers don't draw
12448 // anything despite that colormask...
12449 GL_BlendFunc(GL_ZERO, GL_ONE);
12450 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12451 R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12455 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12457 GL_BlendFunc(GL_ONE, GL_ZERO);
12458 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12459 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12460 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12463 if (skyrendermasked)
12464 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12466 R_Mesh_ResetTextureState();
12467 GL_Color(1, 1, 1, 1);
12470 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12471 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12472 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12474 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12478 // render screenspace normalmap to texture
12479 GL_DepthMask(true);
12480 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12485 // bind lightmap texture
12487 // water/refraction/reflection/camera surfaces have to be handled specially
12488 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)) && !r_waterstate.renderingscene)
12490 int start, end, startplaneindex;
12491 for (start = 0;start < texturenumsurfaces;start = end)
12493 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12494 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12496 // now that we have a batch using the same planeindex, render it
12497 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
12499 // render water or distortion background
12500 GL_DepthMask(true);
12501 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));
12503 // blend surface on top
12504 GL_DepthMask(false);
12505 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12508 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) && !r_waterstate.renderingscene)
12510 // render surface with reflection texture as input
12511 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12512 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));
12519 // render surface batch normally
12520 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12521 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12525 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12527 // OpenGL 1.3 path - anything not completely ancient
12528 qboolean applycolor;
12531 const texturelayer_t *layer;
12532 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);
12533 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12535 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12538 int layertexrgbscale;
12539 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12541 if (layerindex == 0)
12542 GL_AlphaTest(true);
12545 GL_AlphaTest(false);
12546 GL_DepthFunc(GL_EQUAL);
12549 GL_DepthMask(layer->depthmask && writedepth);
12550 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12551 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12553 layertexrgbscale = 4;
12554 VectorScale(layer->color, 0.25f, layercolor);
12556 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12558 layertexrgbscale = 2;
12559 VectorScale(layer->color, 0.5f, layercolor);
12563 layertexrgbscale = 1;
12564 VectorScale(layer->color, 1.0f, layercolor);
12566 layercolor[3] = layer->color[3];
12567 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12568 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12569 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12570 switch (layer->type)
12572 case TEXTURELAYERTYPE_LITTEXTURE:
12573 // single-pass lightmapped texture with 2x rgbscale
12574 R_Mesh_TexBind(0, r_texture_white);
12575 R_Mesh_TexMatrix(0, NULL);
12576 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12577 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12578 R_Mesh_TexBind(1, layer->texture);
12579 R_Mesh_TexMatrix(1, &layer->texmatrix);
12580 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12581 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12582 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12583 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12584 else if (FAKELIGHT_ENABLED)
12585 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12586 else if (rsurface.uselightmaptexture)
12587 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12589 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12591 case TEXTURELAYERTYPE_TEXTURE:
12592 // singletexture unlit texture with transparency support
12593 R_Mesh_TexBind(0, layer->texture);
12594 R_Mesh_TexMatrix(0, &layer->texmatrix);
12595 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12596 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12597 R_Mesh_TexBind(1, 0);
12598 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12599 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12601 case TEXTURELAYERTYPE_FOG:
12602 // singletexture fogging
12603 if (layer->texture)
12605 R_Mesh_TexBind(0, layer->texture);
12606 R_Mesh_TexMatrix(0, &layer->texmatrix);
12607 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12608 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12612 R_Mesh_TexBind(0, 0);
12613 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12615 R_Mesh_TexBind(1, 0);
12616 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12617 // generate a color array for the fog pass
12618 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12619 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12623 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12626 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12628 GL_DepthFunc(GL_LEQUAL);
12629 GL_AlphaTest(false);
12633 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12635 // OpenGL 1.1 - crusty old voodoo path
12638 const texturelayer_t *layer;
12639 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);
12640 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12642 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12644 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12646 if (layerindex == 0)
12647 GL_AlphaTest(true);
12650 GL_AlphaTest(false);
12651 GL_DepthFunc(GL_EQUAL);
12654 GL_DepthMask(layer->depthmask && writedepth);
12655 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12656 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12657 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12658 switch (layer->type)
12660 case TEXTURELAYERTYPE_LITTEXTURE:
12661 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12663 // two-pass lit texture with 2x rgbscale
12664 // first the lightmap pass
12665 R_Mesh_TexBind(0, r_texture_white);
12666 R_Mesh_TexMatrix(0, NULL);
12667 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12668 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12669 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12670 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12671 else if (FAKELIGHT_ENABLED)
12672 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12673 else if (rsurface.uselightmaptexture)
12674 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12676 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12677 // then apply the texture to it
12678 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12679 R_Mesh_TexBind(0, layer->texture);
12680 R_Mesh_TexMatrix(0, &layer->texmatrix);
12681 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12682 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12683 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);
12687 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12688 R_Mesh_TexBind(0, layer->texture);
12689 R_Mesh_TexMatrix(0, &layer->texmatrix);
12690 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12691 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12692 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12693 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);
12695 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);
12698 case TEXTURELAYERTYPE_TEXTURE:
12699 // singletexture unlit texture with transparency support
12700 R_Mesh_TexBind(0, layer->texture);
12701 R_Mesh_TexMatrix(0, &layer->texmatrix);
12702 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12703 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12704 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);
12706 case TEXTURELAYERTYPE_FOG:
12707 // singletexture fogging
12708 if (layer->texture)
12710 R_Mesh_TexBind(0, layer->texture);
12711 R_Mesh_TexMatrix(0, &layer->texmatrix);
12712 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12713 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12717 R_Mesh_TexBind(0, 0);
12718 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12720 // generate a color array for the fog pass
12721 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12722 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12726 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12729 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12731 GL_DepthFunc(GL_LEQUAL);
12732 GL_AlphaTest(false);
12736 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12740 r_vertexgeneric_t *batchvertex;
12743 GL_AlphaTest(false);
12744 R_Mesh_ResetTextureState();
12745 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12747 if(rsurface.texture && rsurface.texture->currentskinframe)
12749 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12750 c[3] *= rsurface.texture->currentalpha;
12760 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12762 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12763 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12764 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12767 // brighten it up (as texture value 127 means "unlit")
12768 c[0] *= 2 * r_refdef.view.colorscale;
12769 c[1] *= 2 * r_refdef.view.colorscale;
12770 c[2] *= 2 * r_refdef.view.colorscale;
12772 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12773 c[3] *= r_wateralpha.value;
12775 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12777 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12778 GL_DepthMask(false);
12780 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12782 GL_BlendFunc(GL_ONE, GL_ONE);
12783 GL_DepthMask(false);
12785 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12787 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12788 GL_DepthMask(false);
12790 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12792 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12793 GL_DepthMask(false);
12797 GL_BlendFunc(GL_ONE, GL_ZERO);
12798 GL_DepthMask(writedepth);
12801 if (r_showsurfaces.integer == 3)
12803 rsurface.passcolor4f = NULL;
12805 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12807 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12809 rsurface.passcolor4f = NULL;
12810 rsurface.passcolor4f_vertexbuffer = 0;
12811 rsurface.passcolor4f_bufferoffset = 0;
12813 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12815 qboolean applycolor = true;
12818 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12820 r_refdef.lightmapintensity = 1;
12821 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12822 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12824 else if (FAKELIGHT_ENABLED)
12826 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12828 r_refdef.lightmapintensity = r_fakelight_intensity.value;
12829 RSurf_DrawBatch_GL11_ApplyFakeLight();
12830 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12834 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12836 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12837 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12838 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12841 if(!rsurface.passcolor4f)
12842 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12844 RSurf_DrawBatch_GL11_ApplyAmbient();
12845 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12846 if(r_refdef.fogenabled)
12847 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12848 RSurf_DrawBatch_GL11_ClampColor();
12850 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12851 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12854 else if (!r_refdef.view.showdebug)
12856 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12857 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12858 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12860 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12861 Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12863 R_Mesh_PrepareVertices_Generic_Unlock();
12866 else if (r_showsurfaces.integer == 4)
12868 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12869 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12870 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12872 unsigned char c = vi << 3;
12873 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12874 Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12876 R_Mesh_PrepareVertices_Generic_Unlock();
12879 else if (r_showsurfaces.integer == 2)
12882 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12883 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12884 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12886 unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12887 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12888 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12889 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12890 Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12891 Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12892 Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12894 R_Mesh_PrepareVertices_Generic_Unlock();
12895 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12899 int texturesurfaceindex;
12901 const msurface_t *surface;
12902 unsigned char surfacecolor4ub[4];
12903 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12904 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12906 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12908 surface = texturesurfacelist[texturesurfaceindex];
12909 k = (int)(((size_t)surface) / sizeof(msurface_t));
12910 Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
12911 for (j = 0;j < surface->num_vertices;j++)
12913 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12914 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
12918 R_Mesh_PrepareVertices_Generic_Unlock();
12923 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12926 RSurf_SetupDepthAndCulling();
12927 if (r_showsurfaces.integer)
12929 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12932 switch (vid.renderpath)
12934 case RENDERPATH_GL20:
12935 case RENDERPATH_CGGL:
12936 case RENDERPATH_D3D9:
12937 case RENDERPATH_D3D10:
12938 case RENDERPATH_D3D11:
12939 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12941 case RENDERPATH_GL13:
12942 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12944 case RENDERPATH_GL11:
12945 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12951 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12954 RSurf_SetupDepthAndCulling();
12955 if (r_showsurfaces.integer)
12957 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12960 switch (vid.renderpath)
12962 case RENDERPATH_GL20:
12963 case RENDERPATH_CGGL:
12964 case RENDERPATH_D3D9:
12965 case RENDERPATH_D3D10:
12966 case RENDERPATH_D3D11:
12967 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12969 case RENDERPATH_GL13:
12970 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12972 case RENDERPATH_GL11:
12973 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12979 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12982 int texturenumsurfaces, endsurface;
12983 texture_t *texture;
12984 const msurface_t *surface;
12985 #define MAXBATCH_TRANSPARENTSURFACES 256
12986 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
12988 // if the model is static it doesn't matter what value we give for
12989 // wantnormals and wanttangents, so this logic uses only rules applicable
12990 // to a model, knowing that they are meaningless otherwise
12991 if (ent == r_refdef.scene.worldentity)
12992 RSurf_ActiveWorldEntity();
12993 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12994 RSurf_ActiveModelEntity(ent, false, false, false);
12997 switch (vid.renderpath)
12999 case RENDERPATH_GL20:
13000 case RENDERPATH_CGGL:
13001 case RENDERPATH_D3D9:
13002 case RENDERPATH_D3D10:
13003 case RENDERPATH_D3D11:
13004 RSurf_ActiveModelEntity(ent, true, true, false);
13006 case RENDERPATH_GL13:
13007 case RENDERPATH_GL11:
13008 RSurf_ActiveModelEntity(ent, true, false, false);
13013 if (r_transparentdepthmasking.integer)
13015 qboolean setup = false;
13016 for (i = 0;i < numsurfaces;i = j)
13019 surface = rsurface.modelsurfaces + surfacelist[i];
13020 texture = surface->texture;
13021 rsurface.texture = R_GetCurrentTexture(texture);
13022 rsurface.lightmaptexture = NULL;
13023 rsurface.deluxemaptexture = NULL;
13024 rsurface.uselightmaptexture = false;
13025 // scan ahead until we find a different texture
13026 endsurface = min(i + 1024, numsurfaces);
13027 texturenumsurfaces = 0;
13028 texturesurfacelist[texturenumsurfaces++] = surface;
13029 for (;j < endsurface;j++)
13031 surface = rsurface.modelsurfaces + surfacelist[j];
13032 if (texture != surface->texture)
13034 texturesurfacelist[texturenumsurfaces++] = surface;
13036 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
13038 // render the range of surfaces as depth
13042 GL_ColorMask(0,0,0,0);
13044 GL_DepthTest(true);
13045 GL_BlendFunc(GL_ONE, GL_ZERO);
13046 GL_DepthMask(true);
13047 GL_AlphaTest(false);
13048 R_Mesh_ResetTextureState();
13049 R_SetupShader_DepthOrShadow();
13051 RSurf_SetupDepthAndCulling();
13052 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13053 R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13057 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
13060 for (i = 0;i < numsurfaces;i = j)
13063 surface = rsurface.modelsurfaces + surfacelist[i];
13064 texture = surface->texture;
13065 rsurface.texture = R_GetCurrentTexture(texture);
13066 // scan ahead until we find a different texture
13067 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
13068 texturenumsurfaces = 0;
13069 texturesurfacelist[texturenumsurfaces++] = surface;
13070 if(FAKELIGHT_ENABLED)
13072 rsurface.lightmaptexture = NULL;
13073 rsurface.deluxemaptexture = NULL;
13074 rsurface.uselightmaptexture = false;
13075 for (;j < endsurface;j++)
13077 surface = rsurface.modelsurfaces + surfacelist[j];
13078 if (texture != surface->texture)
13080 texturesurfacelist[texturenumsurfaces++] = surface;
13085 rsurface.lightmaptexture = surface->lightmaptexture;
13086 rsurface.deluxemaptexture = surface->deluxemaptexture;
13087 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
13088 for (;j < endsurface;j++)
13090 surface = rsurface.modelsurfaces + surfacelist[j];
13091 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
13093 texturesurfacelist[texturenumsurfaces++] = surface;
13096 // render the range of surfaces
13097 if (ent == r_refdef.scene.worldentity)
13098 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13100 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13102 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13103 GL_AlphaTest(false);
13106 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
13108 // transparent surfaces get pushed off into the transparent queue
13109 int surfacelistindex;
13110 const msurface_t *surface;
13111 vec3_t tempcenter, center;
13112 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
13114 surface = texturesurfacelist[surfacelistindex];
13115 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
13116 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
13117 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
13118 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
13119 if (queueentity->transparent_offset) // transparent offset
13121 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
13122 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
13123 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
13125 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
13129 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
13131 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
13133 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
13135 RSurf_SetupDepthAndCulling();
13136 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13137 R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13141 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
13143 const entity_render_t *queueentity = r_refdef.scene.worldentity;
13146 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13149 if (!rsurface.texture->currentnumlayers)
13151 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13152 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13154 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13156 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13157 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13158 else if (!rsurface.texture->currentnumlayers)
13160 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13162 // in the deferred case, transparent surfaces were queued during prepass
13163 if (!r_shadow_usingdeferredprepass)
13164 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13168 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13169 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13174 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13177 texture_t *texture;
13178 // break the surface list down into batches by texture and use of lightmapping
13179 for (i = 0;i < numsurfaces;i = j)
13182 // texture is the base texture pointer, rsurface.texture is the
13183 // current frame/skin the texture is directing us to use (for example
13184 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13185 // use skin 1 instead)
13186 texture = surfacelist[i]->texture;
13187 rsurface.texture = R_GetCurrentTexture(texture);
13188 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13190 // if this texture is not the kind we want, skip ahead to the next one
13191 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13195 if(FAKELIGHT_ENABLED || depthonly || prepass)
13197 rsurface.lightmaptexture = NULL;
13198 rsurface.deluxemaptexture = NULL;
13199 rsurface.uselightmaptexture = false;
13200 // simply scan ahead until we find a different texture or lightmap state
13201 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13206 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13207 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13208 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13209 // simply scan ahead until we find a different texture or lightmap state
13210 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13213 // render the range of surfaces
13214 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
13218 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
13222 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13225 if (!rsurface.texture->currentnumlayers)
13227 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13228 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13230 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13232 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13233 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13234 else if (!rsurface.texture->currentnumlayers)
13236 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13238 // in the deferred case, transparent surfaces were queued during prepass
13239 if (!r_shadow_usingdeferredprepass)
13240 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13244 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13245 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13250 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13253 texture_t *texture;
13254 // break the surface list down into batches by texture and use of lightmapping
13255 for (i = 0;i < numsurfaces;i = j)
13258 // texture is the base texture pointer, rsurface.texture is the
13259 // current frame/skin the texture is directing us to use (for example
13260 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13261 // use skin 1 instead)
13262 texture = surfacelist[i]->texture;
13263 rsurface.texture = R_GetCurrentTexture(texture);
13264 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13266 // if this texture is not the kind we want, skip ahead to the next one
13267 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13271 if(FAKELIGHT_ENABLED || depthonly || prepass)
13273 rsurface.lightmaptexture = NULL;
13274 rsurface.deluxemaptexture = NULL;
13275 rsurface.uselightmaptexture = false;
13276 // simply scan ahead until we find a different texture or lightmap state
13277 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13282 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13283 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13284 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13285 // simply scan ahead until we find a different texture or lightmap state
13286 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13289 // render the range of surfaces
13290 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
13294 float locboxvertex3f[6*4*3] =
13296 1,0,1, 1,0,0, 1,1,0, 1,1,1,
13297 0,1,1, 0,1,0, 0,0,0, 0,0,1,
13298 1,1,1, 1,1,0, 0,1,0, 0,1,1,
13299 0,0,1, 0,0,0, 1,0,0, 1,0,1,
13300 0,0,1, 1,0,1, 1,1,1, 0,1,1,
13301 1,0,0, 0,0,0, 0,1,0, 1,1,0
13304 unsigned short locboxelements[6*2*3] =
13309 12,13,14, 12,14,15,
13310 16,17,18, 16,18,19,
13314 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13317 cl_locnode_t *loc = (cl_locnode_t *)ent;
13319 float vertex3f[6*4*3];
13321 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13322 GL_DepthMask(false);
13323 GL_DepthRange(0, 1);
13324 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13325 GL_DepthTest(true);
13326 GL_CullFace(GL_NONE);
13327 R_EntityMatrix(&identitymatrix);
13329 R_Mesh_ResetTextureState();
13331 i = surfacelist[0];
13332 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13333 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13334 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13335 surfacelist[0] < 0 ? 0.5f : 0.125f);
13337 if (VectorCompare(loc->mins, loc->maxs))
13339 VectorSet(size, 2, 2, 2);
13340 VectorMA(loc->mins, -0.5f, size, mins);
13344 VectorCopy(loc->mins, mins);
13345 VectorSubtract(loc->maxs, loc->mins, size);
13348 for (i = 0;i < 6*4*3;)
13349 for (j = 0;j < 3;j++, i++)
13350 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13352 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13353 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13354 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13357 void R_DrawLocs(void)
13360 cl_locnode_t *loc, *nearestloc;
13362 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13363 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13365 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13366 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13370 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13372 if (decalsystem->decals)
13373 Mem_Free(decalsystem->decals);
13374 memset(decalsystem, 0, sizeof(*decalsystem));
13377 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)
13380 tridecal_t *decals;
13383 // expand or initialize the system
13384 if (decalsystem->maxdecals <= decalsystem->numdecals)
13386 decalsystem_t old = *decalsystem;
13387 qboolean useshortelements;
13388 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13389 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13390 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)));
13391 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13392 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13393 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13394 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13395 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13396 if (decalsystem->numdecals)
13397 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13399 Mem_Free(old.decals);
13400 for (i = 0;i < decalsystem->maxdecals*3;i++)
13401 decalsystem->element3i[i] = i;
13402 if (useshortelements)
13403 for (i = 0;i < decalsystem->maxdecals*3;i++)
13404 decalsystem->element3s[i] = i;
13407 // grab a decal and search for another free slot for the next one
13408 decals = decalsystem->decals;
13409 decal = decalsystem->decals + (i = decalsystem->freedecal++);
13410 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13412 decalsystem->freedecal = i;
13413 if (decalsystem->numdecals <= i)
13414 decalsystem->numdecals = i + 1;
13416 // initialize the decal
13418 decal->triangleindex = triangleindex;
13419 decal->surfaceindex = surfaceindex;
13420 decal->decalsequence = decalsequence;
13421 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13422 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13423 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13424 decal->color4ub[0][3] = 255;
13425 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13426 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13427 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13428 decal->color4ub[1][3] = 255;
13429 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13430 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13431 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13432 decal->color4ub[2][3] = 255;
13433 decal->vertex3f[0][0] = v0[0];
13434 decal->vertex3f[0][1] = v0[1];
13435 decal->vertex3f[0][2] = v0[2];
13436 decal->vertex3f[1][0] = v1[0];
13437 decal->vertex3f[1][1] = v1[1];
13438 decal->vertex3f[1][2] = v1[2];
13439 decal->vertex3f[2][0] = v2[0];
13440 decal->vertex3f[2][1] = v2[1];
13441 decal->vertex3f[2][2] = v2[2];
13442 decal->texcoord2f[0][0] = t0[0];
13443 decal->texcoord2f[0][1] = t0[1];
13444 decal->texcoord2f[1][0] = t1[0];
13445 decal->texcoord2f[1][1] = t1[1];
13446 decal->texcoord2f[2][0] = t2[0];
13447 decal->texcoord2f[2][1] = t2[1];
13450 extern cvar_t cl_decals_bias;
13451 extern cvar_t cl_decals_models;
13452 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13453 // baseparms, parms, temps
13454 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)
13459 const float *vertex3f;
13461 float points[2][9][3];
13468 e = rsurface.modelelement3i + 3*triangleindex;
13470 vertex3f = rsurface.modelvertex3f;
13472 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13474 index = 3*e[cornerindex];
13475 VectorCopy(vertex3f + index, v[cornerindex]);
13478 //TriangleNormal(v[0], v[1], v[2], normal);
13479 //if (DotProduct(normal, localnormal) < 0.0f)
13481 // clip by each of the box planes formed from the projection matrix
13482 // if anything survives, we emit the decal
13483 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]);
13486 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]);
13489 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]);
13492 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]);
13495 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]);
13498 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]);
13501 // some part of the triangle survived, so we have to accept it...
13504 // dynamic always uses the original triangle
13506 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13508 index = 3*e[cornerindex];
13509 VectorCopy(vertex3f + index, v[cornerindex]);
13512 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13514 // convert vertex positions to texcoords
13515 Matrix4x4_Transform(projection, v[cornerindex], temp);
13516 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13517 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13518 // calculate distance fade from the projection origin
13519 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13520 f = bound(0.0f, f, 1.0f);
13521 c[cornerindex][0] = r * f;
13522 c[cornerindex][1] = g * f;
13523 c[cornerindex][2] = b * f;
13524 c[cornerindex][3] = 1.0f;
13525 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13528 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);
13530 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13531 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);
13533 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)
13535 matrix4x4_t projection;
13536 decalsystem_t *decalsystem;
13539 const msurface_t *surface;
13540 const msurface_t *surfaces;
13541 const int *surfacelist;
13542 const texture_t *texture;
13544 int numsurfacelist;
13545 int surfacelistindex;
13548 float localorigin[3];
13549 float localnormal[3];
13550 float localmins[3];
13551 float localmaxs[3];
13554 float planes[6][4];
13557 int bih_triangles_count;
13558 int bih_triangles[256];
13559 int bih_surfaces[256];
13561 decalsystem = &ent->decalsystem;
13562 model = ent->model;
13563 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13565 R_DecalSystem_Reset(&ent->decalsystem);
13569 if (!model->brush.data_leafs && !cl_decals_models.integer)
13571 if (decalsystem->model)
13572 R_DecalSystem_Reset(decalsystem);
13576 if (decalsystem->model != model)
13577 R_DecalSystem_Reset(decalsystem);
13578 decalsystem->model = model;
13580 RSurf_ActiveModelEntity(ent, false, false, false);
13582 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13583 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13584 VectorNormalize(localnormal);
13585 localsize = worldsize*rsurface.inversematrixscale;
13586 localmins[0] = localorigin[0] - localsize;
13587 localmins[1] = localorigin[1] - localsize;
13588 localmins[2] = localorigin[2] - localsize;
13589 localmaxs[0] = localorigin[0] + localsize;
13590 localmaxs[1] = localorigin[1] + localsize;
13591 localmaxs[2] = localorigin[2] + localsize;
13593 //VectorCopy(localnormal, planes[4]);
13594 //VectorVectors(planes[4], planes[2], planes[0]);
13595 AnglesFromVectors(angles, localnormal, NULL, false);
13596 AngleVectors(angles, planes[0], planes[2], planes[4]);
13597 VectorNegate(planes[0], planes[1]);
13598 VectorNegate(planes[2], planes[3]);
13599 VectorNegate(planes[4], planes[5]);
13600 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13601 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13602 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13603 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13604 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13605 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13610 matrix4x4_t forwardprojection;
13611 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13612 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13617 float projectionvector[4][3];
13618 VectorScale(planes[0], ilocalsize, projectionvector[0]);
13619 VectorScale(planes[2], ilocalsize, projectionvector[1]);
13620 VectorScale(planes[4], ilocalsize, projectionvector[2]);
13621 projectionvector[0][0] = planes[0][0] * ilocalsize;
13622 projectionvector[0][1] = planes[1][0] * ilocalsize;
13623 projectionvector[0][2] = planes[2][0] * ilocalsize;
13624 projectionvector[1][0] = planes[0][1] * ilocalsize;
13625 projectionvector[1][1] = planes[1][1] * ilocalsize;
13626 projectionvector[1][2] = planes[2][1] * ilocalsize;
13627 projectionvector[2][0] = planes[0][2] * ilocalsize;
13628 projectionvector[2][1] = planes[1][2] * ilocalsize;
13629 projectionvector[2][2] = planes[2][2] * ilocalsize;
13630 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13631 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13632 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13633 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13637 dynamic = model->surfmesh.isanimated;
13638 numsurfacelist = model->nummodelsurfaces;
13639 surfacelist = model->sortedmodelsurfaces;
13640 surfaces = model->data_surfaces;
13643 bih_triangles_count = -1;
13646 if(model->render_bih.numleafs)
13647 bih = &model->render_bih;
13648 else if(model->collision_bih.numleafs)
13649 bih = &model->collision_bih;
13652 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13653 if(bih_triangles_count == 0)
13655 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13657 if(bih_triangles_count > 0)
13659 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13661 surfaceindex = bih_surfaces[triangleindex];
13662 surface = surfaces + surfaceindex;
13663 texture = surface->texture;
13664 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13666 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13668 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13673 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13675 surfaceindex = surfacelist[surfacelistindex];
13676 surface = surfaces + surfaceindex;
13677 // check cull box first because it rejects more than any other check
13678 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13680 // skip transparent surfaces
13681 texture = surface->texture;
13682 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13684 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13686 numtriangles = surface->num_triangles;
13687 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13688 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13693 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13694 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)
13696 int renderentityindex;
13697 float worldmins[3];
13698 float worldmaxs[3];
13699 entity_render_t *ent;
13701 if (!cl_decals_newsystem.integer)
13704 worldmins[0] = worldorigin[0] - worldsize;
13705 worldmins[1] = worldorigin[1] - worldsize;
13706 worldmins[2] = worldorigin[2] - worldsize;
13707 worldmaxs[0] = worldorigin[0] + worldsize;
13708 worldmaxs[1] = worldorigin[1] + worldsize;
13709 worldmaxs[2] = worldorigin[2] + worldsize;
13711 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13713 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13715 ent = r_refdef.scene.entities[renderentityindex];
13716 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13719 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13723 typedef struct r_decalsystem_splatqueue_s
13725 vec3_t worldorigin;
13726 vec3_t worldnormal;
13732 r_decalsystem_splatqueue_t;
13734 int r_decalsystem_numqueued = 0;
13735 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13737 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)
13739 r_decalsystem_splatqueue_t *queue;
13741 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13744 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13745 VectorCopy(worldorigin, queue->worldorigin);
13746 VectorCopy(worldnormal, queue->worldnormal);
13747 Vector4Set(queue->color, r, g, b, a);
13748 Vector4Set(queue->tcrange, s1, t1, s2, t2);
13749 queue->worldsize = worldsize;
13750 queue->decalsequence = cl.decalsequence++;
13753 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13756 r_decalsystem_splatqueue_t *queue;
13758 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13759 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);
13760 r_decalsystem_numqueued = 0;
13763 extern cvar_t cl_decals_max;
13764 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13767 decalsystem_t *decalsystem = &ent->decalsystem;
13774 if (!decalsystem->numdecals)
13777 if (r_showsurfaces.integer)
13780 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13782 R_DecalSystem_Reset(decalsystem);
13786 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13787 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13789 if (decalsystem->lastupdatetime)
13790 frametime = (cl.time - decalsystem->lastupdatetime);
13793 decalsystem->lastupdatetime = cl.time;
13794 decal = decalsystem->decals;
13795 numdecals = decalsystem->numdecals;
13797 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13799 if (decal->color4ub[0][3])
13801 decal->lived += frametime;
13802 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13804 memset(decal, 0, sizeof(*decal));
13805 if (decalsystem->freedecal > i)
13806 decalsystem->freedecal = i;
13810 decal = decalsystem->decals;
13811 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13814 // collapse the array by shuffling the tail decals into the gaps
13817 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13818 decalsystem->freedecal++;
13819 if (decalsystem->freedecal == numdecals)
13821 decal[decalsystem->freedecal] = decal[--numdecals];
13824 decalsystem->numdecals = numdecals;
13826 if (numdecals <= 0)
13828 // if there are no decals left, reset decalsystem
13829 R_DecalSystem_Reset(decalsystem);
13833 extern skinframe_t *decalskinframe;
13834 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13837 decalsystem_t *decalsystem = &ent->decalsystem;
13846 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13849 numdecals = decalsystem->numdecals;
13853 if (r_showsurfaces.integer)
13856 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13858 R_DecalSystem_Reset(decalsystem);
13862 // if the model is static it doesn't matter what value we give for
13863 // wantnormals and wanttangents, so this logic uses only rules applicable
13864 // to a model, knowing that they are meaningless otherwise
13865 if (ent == r_refdef.scene.worldentity)
13866 RSurf_ActiveWorldEntity();
13868 RSurf_ActiveModelEntity(ent, false, false, false);
13870 decalsystem->lastupdatetime = cl.time;
13871 decal = decalsystem->decals;
13873 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13875 // update vertex positions for animated models
13876 v3f = decalsystem->vertex3f;
13877 c4f = decalsystem->color4f;
13878 t2f = decalsystem->texcoord2f;
13879 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13881 if (!decal->color4ub[0][3])
13884 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13887 // update color values for fading decals
13888 if (decal->lived >= cl_decals_time.value)
13890 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13891 alpha *= (1.0f/255.0f);
13894 alpha = 1.0f/255.0f;
13896 c4f[ 0] = decal->color4ub[0][0] * alpha;
13897 c4f[ 1] = decal->color4ub[0][1] * alpha;
13898 c4f[ 2] = decal->color4ub[0][2] * alpha;
13900 c4f[ 4] = decal->color4ub[1][0] * alpha;
13901 c4f[ 5] = decal->color4ub[1][1] * alpha;
13902 c4f[ 6] = decal->color4ub[1][2] * alpha;
13904 c4f[ 8] = decal->color4ub[2][0] * alpha;
13905 c4f[ 9] = decal->color4ub[2][1] * alpha;
13906 c4f[10] = decal->color4ub[2][2] * alpha;
13909 t2f[0] = decal->texcoord2f[0][0];
13910 t2f[1] = decal->texcoord2f[0][1];
13911 t2f[2] = decal->texcoord2f[1][0];
13912 t2f[3] = decal->texcoord2f[1][1];
13913 t2f[4] = decal->texcoord2f[2][0];
13914 t2f[5] = decal->texcoord2f[2][1];
13916 // update vertex positions for animated models
13917 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13919 e = rsurface.modelelement3i + 3*decal->triangleindex;
13920 VectorCopy(rsurface.modelvertexposition[e[0]].vertex3f, v3f);
13921 VectorCopy(rsurface.modelvertexposition[e[1]].vertex3f, v3f + 3);
13922 VectorCopy(rsurface.modelvertexposition[e[2]].vertex3f, v3f + 6);
13926 VectorCopy(decal->vertex3f[0], v3f);
13927 VectorCopy(decal->vertex3f[1], v3f + 3);
13928 VectorCopy(decal->vertex3f[2], v3f + 6);
13931 if (r_refdef.fogenabled)
13933 alpha = RSurf_FogVertex(v3f);
13934 VectorScale(c4f, alpha, c4f);
13935 alpha = RSurf_FogVertex(v3f + 3);
13936 VectorScale(c4f + 4, alpha, c4f + 4);
13937 alpha = RSurf_FogVertex(v3f + 6);
13938 VectorScale(c4f + 8, alpha, c4f + 8);
13949 r_refdef.stats.drawndecals += numtris;
13951 // now render the decals all at once
13952 // (this assumes they all use one particle font texture!)
13953 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);
13954 R_Mesh_ResetTextureState();
13955 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
13956 GL_DepthMask(false);
13957 GL_DepthRange(0, 1);
13958 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
13959 GL_DepthTest(true);
13960 GL_CullFace(GL_NONE);
13961 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
13962 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
13963 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
13967 static void R_DrawModelDecals(void)
13971 // fade faster when there are too many decals
13972 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13973 for (i = 0;i < r_refdef.scene.numentities;i++)
13974 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13976 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
13977 for (i = 0;i < r_refdef.scene.numentities;i++)
13978 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13979 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
13981 R_DecalSystem_ApplySplatEntitiesQueue();
13983 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13984 for (i = 0;i < r_refdef.scene.numentities;i++)
13985 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13987 r_refdef.stats.totaldecals += numdecals;
13989 if (r_showsurfaces.integer)
13992 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
13994 for (i = 0;i < r_refdef.scene.numentities;i++)
13996 if (!r_refdef.viewcache.entityvisible[i])
13998 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13999 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
14003 extern cvar_t mod_collision_bih;
14004 void R_DrawDebugModel(void)
14006 entity_render_t *ent = rsurface.entity;
14007 int i, j, k, l, flagsmask;
14008 const msurface_t *surface;
14009 dp_model_t *model = ent->model;
14012 switch(vid.renderpath)
14014 case RENDERPATH_GL11:
14015 case RENDERPATH_GL13:
14016 case RENDERPATH_GL20:
14017 case RENDERPATH_CGGL:
14019 case RENDERPATH_D3D9:
14020 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14022 case RENDERPATH_D3D10:
14023 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14025 case RENDERPATH_D3D11:
14026 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14030 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
14032 R_Mesh_ResetTextureState();
14033 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
14034 GL_DepthRange(0, 1);
14035 GL_DepthTest(!r_showdisabledepthtest.integer);
14036 GL_DepthMask(false);
14037 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14039 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
14043 qboolean cullbox = ent == r_refdef.scene.worldentity;
14044 const q3mbrush_t *brush;
14045 const bih_t *bih = &model->collision_bih;
14046 const bih_leaf_t *bihleaf;
14047 float vertex3f[3][3];
14048 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
14050 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
14052 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
14054 switch (bihleaf->type)
14057 brush = model->brush.data_brushes + bihleaf->itemindex;
14058 if (brush->colbrushf && brush->colbrushf->numtriangles)
14060 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);
14061 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
14062 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
14065 case BIH_COLLISIONTRIANGLE:
14066 triangleindex = bihleaf->itemindex;
14067 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
14068 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
14069 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
14070 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);
14071 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14072 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14074 case BIH_RENDERTRIANGLE:
14075 triangleindex = bihleaf->itemindex;
14076 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
14077 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
14078 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
14079 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);
14080 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14081 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14087 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
14089 if (r_showtris.integer || r_shownormals.integer)
14091 if (r_showdisabledepthtest.integer)
14093 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14094 GL_DepthMask(false);
14098 GL_BlendFunc(GL_ONE, GL_ZERO);
14099 GL_DepthMask(true);
14101 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
14103 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
14105 rsurface.texture = R_GetCurrentTexture(surface->texture);
14106 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
14108 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
14109 if (r_showtris.value > 0)
14111 if (!rsurface.texture->currentlayers->depthmask)
14112 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
14113 else if (ent == r_refdef.scene.worldentity)
14114 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
14116 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
14117 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
14118 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
14120 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
14123 if (r_shownormals.value < 0)
14125 qglBegin(GL_LINES);
14126 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14128 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14129 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14130 qglVertex3f(v[0], v[1], v[2]);
14131 VectorMA(v, -r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14132 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14133 qglVertex3f(v[0], v[1], v[2]);
14138 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
14140 qglBegin(GL_LINES);
14141 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14143 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14144 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14145 qglVertex3f(v[0], v[1], v[2]);
14146 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14147 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14148 qglVertex3f(v[0], v[1], v[2]);
14152 qglBegin(GL_LINES);
14153 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14155 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14156 GL_Color(0, r_refdef.view.colorscale, 0, 1);
14157 qglVertex3f(v[0], v[1], v[2]);
14158 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
14159 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14160 qglVertex3f(v[0], v[1], v[2]);
14164 qglBegin(GL_LINES);
14165 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14167 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14168 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14169 qglVertex3f(v[0], v[1], v[2]);
14170 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14171 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14172 qglVertex3f(v[0], v[1], v[2]);
14179 rsurface.texture = NULL;
14183 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
14184 int r_maxsurfacelist = 0;
14185 const msurface_t **r_surfacelist = NULL;
14186 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14188 int i, j, endj, flagsmask;
14189 dp_model_t *model = r_refdef.scene.worldmodel;
14190 msurface_t *surfaces;
14191 unsigned char *update;
14192 int numsurfacelist = 0;
14196 if (r_maxsurfacelist < model->num_surfaces)
14198 r_maxsurfacelist = model->num_surfaces;
14200 Mem_Free((msurface_t**)r_surfacelist);
14201 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14204 RSurf_ActiveWorldEntity();
14206 surfaces = model->data_surfaces;
14207 update = model->brushq1.lightmapupdateflags;
14209 // update light styles on this submodel
14210 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14212 model_brush_lightstyleinfo_t *style;
14213 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14215 if (style->value != r_refdef.scene.lightstylevalue[style->style])
14217 int *list = style->surfacelist;
14218 style->value = r_refdef.scene.lightstylevalue[style->style];
14219 for (j = 0;j < style->numsurfaces;j++)
14220 update[list[j]] = true;
14225 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14229 R_DrawDebugModel();
14230 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14234 rsurface.lightmaptexture = NULL;
14235 rsurface.deluxemaptexture = NULL;
14236 rsurface.uselightmaptexture = false;
14237 rsurface.texture = NULL;
14238 rsurface.rtlight = NULL;
14239 numsurfacelist = 0;
14240 // add visible surfaces to draw list
14241 for (i = 0;i < model->nummodelsurfaces;i++)
14243 j = model->sortedmodelsurfaces[i];
14244 if (r_refdef.viewcache.world_surfacevisible[j])
14245 r_surfacelist[numsurfacelist++] = surfaces + j;
14247 // update lightmaps if needed
14248 if (model->brushq1.firstrender)
14250 model->brushq1.firstrender = false;
14251 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14253 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14257 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14258 if (r_refdef.viewcache.world_surfacevisible[j])
14260 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14262 // don't do anything if there were no surfaces
14263 if (!numsurfacelist)
14265 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14268 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14269 GL_AlphaTest(false);
14271 // add to stats if desired
14272 if (r_speeds.integer && !skysurfaces && !depthonly)
14274 r_refdef.stats.world_surfaces += numsurfacelist;
14275 for (j = 0;j < numsurfacelist;j++)
14276 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
14279 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14282 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14284 int i, j, endj, flagsmask;
14285 dp_model_t *model = ent->model;
14286 msurface_t *surfaces;
14287 unsigned char *update;
14288 int numsurfacelist = 0;
14292 if (r_maxsurfacelist < model->num_surfaces)
14294 r_maxsurfacelist = model->num_surfaces;
14296 Mem_Free((msurface_t **)r_surfacelist);
14297 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14300 // if the model is static it doesn't matter what value we give for
14301 // wantnormals and wanttangents, so this logic uses only rules applicable
14302 // to a model, knowing that they are meaningless otherwise
14303 if (ent == r_refdef.scene.worldentity)
14304 RSurf_ActiveWorldEntity();
14305 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14306 RSurf_ActiveModelEntity(ent, false, false, false);
14308 RSurf_ActiveModelEntity(ent, true, true, true);
14309 else if (depthonly)
14311 switch (vid.renderpath)
14313 case RENDERPATH_GL20:
14314 case RENDERPATH_CGGL:
14315 case RENDERPATH_D3D9:
14316 case RENDERPATH_D3D10:
14317 case RENDERPATH_D3D11:
14318 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14320 case RENDERPATH_GL13:
14321 case RENDERPATH_GL11:
14322 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14328 switch (vid.renderpath)
14330 case RENDERPATH_GL20:
14331 case RENDERPATH_CGGL:
14332 case RENDERPATH_D3D9:
14333 case RENDERPATH_D3D10:
14334 case RENDERPATH_D3D11:
14335 RSurf_ActiveModelEntity(ent, true, true, false);
14337 case RENDERPATH_GL13:
14338 case RENDERPATH_GL11:
14339 RSurf_ActiveModelEntity(ent, true, false, false);
14344 surfaces = model->data_surfaces;
14345 update = model->brushq1.lightmapupdateflags;
14347 // update light styles
14348 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14350 model_brush_lightstyleinfo_t *style;
14351 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14353 if (style->value != r_refdef.scene.lightstylevalue[style->style])
14355 int *list = style->surfacelist;
14356 style->value = r_refdef.scene.lightstylevalue[style->style];
14357 for (j = 0;j < style->numsurfaces;j++)
14358 update[list[j]] = true;
14363 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14367 R_DrawDebugModel();
14368 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14372 rsurface.lightmaptexture = NULL;
14373 rsurface.deluxemaptexture = NULL;
14374 rsurface.uselightmaptexture = false;
14375 rsurface.texture = NULL;
14376 rsurface.rtlight = NULL;
14377 numsurfacelist = 0;
14378 // add visible surfaces to draw list
14379 for (i = 0;i < model->nummodelsurfaces;i++)
14380 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14381 // don't do anything if there were no surfaces
14382 if (!numsurfacelist)
14384 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14387 // update lightmaps if needed
14391 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14396 R_BuildLightMap(ent, surfaces + j);
14401 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14403 R_BuildLightMap(ent, surfaces + j);
14404 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14405 GL_AlphaTest(false);
14407 // add to stats if desired
14408 if (r_speeds.integer && !skysurfaces && !depthonly)
14410 r_refdef.stats.entities_surfaces += numsurfacelist;
14411 for (j = 0;j < numsurfacelist;j++)
14412 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14415 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14418 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14420 static texture_t texture;
14421 static msurface_t surface;
14422 const msurface_t *surfacelist = &surface;
14424 // fake enough texture and surface state to render this geometry
14426 texture.update_lastrenderframe = -1; // regenerate this texture
14427 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14428 texture.currentskinframe = skinframe;
14429 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14430 texture.offsetmapping = OFFSETMAPPING_OFF;
14431 texture.offsetscale = 1;
14432 texture.specularscalemod = 1;
14433 texture.specularpowermod = 1;
14435 surface.texture = &texture;
14436 surface.num_triangles = numtriangles;
14437 surface.num_firsttriangle = firsttriangle;
14438 surface.num_vertices = numvertices;
14439 surface.num_firstvertex = firstvertex;
14442 rsurface.texture = R_GetCurrentTexture(surface.texture);
14443 rsurface.lightmaptexture = NULL;
14444 rsurface.deluxemaptexture = NULL;
14445 rsurface.uselightmaptexture = false;
14446 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14449 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)
14451 static msurface_t surface;
14452 const msurface_t *surfacelist = &surface;
14454 // fake enough texture and surface state to render this geometry
14456 surface.texture = texture;
14457 surface.num_triangles = numtriangles;
14458 surface.num_firsttriangle = firsttriangle;
14459 surface.num_vertices = numvertices;
14460 surface.num_firstvertex = firstvertex;
14463 rsurface.texture = R_GetCurrentTexture(surface.texture);
14464 rsurface.lightmaptexture = NULL;
14465 rsurface.deluxemaptexture = NULL;
14466 rsurface.uselightmaptexture = false;
14467 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);