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)"};
151 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
152 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
153 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
154 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
156 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)"};
157 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
158 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"};
159 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
160 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
161 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
163 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
164 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
165 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
166 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
168 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
169 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
170 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
171 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
172 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
173 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
174 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
176 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
177 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
178 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
179 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)"};
181 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"};
183 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"};
185 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
187 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
188 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"};
189 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
190 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
191 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
192 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
193 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "15", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
194 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
195 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
197 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
198 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"};
200 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
202 extern cvar_t v_glslgamma;
204 extern qboolean v_flipped_state;
206 static struct r_bloomstate_s
211 int bloomwidth, bloomheight;
213 int screentexturewidth, screentextureheight;
214 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
216 int bloomtexturewidth, bloomtextureheight;
217 rtexture_t *texture_bloom;
219 // arrays for rendering the screen passes
220 float screentexcoord2f[8];
221 float bloomtexcoord2f[8];
222 float offsettexcoord2f[8];
224 r_viewport_t viewport;
228 r_waterstate_t r_waterstate;
230 /// shadow volume bsp struct with automatically growing nodes buffer
233 rtexture_t *r_texture_blanknormalmap;
234 rtexture_t *r_texture_white;
235 rtexture_t *r_texture_grey128;
236 rtexture_t *r_texture_black;
237 rtexture_t *r_texture_notexture;
238 rtexture_t *r_texture_whitecube;
239 rtexture_t *r_texture_normalizationcube;
240 rtexture_t *r_texture_fogattenuation;
241 rtexture_t *r_texture_fogheighttexture;
242 rtexture_t *r_texture_gammaramps;
243 unsigned int r_texture_gammaramps_serial;
244 //rtexture_t *r_texture_fogintensity;
245 rtexture_t *r_texture_reflectcube;
247 // TODO: hash lookups?
248 typedef struct cubemapinfo_s
255 int r_texture_numcubemaps;
256 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
258 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
259 unsigned int r_numqueries;
260 unsigned int r_maxqueries;
262 typedef struct r_qwskincache_s
264 char name[MAX_QPATH];
265 skinframe_t *skinframe;
269 static r_qwskincache_t *r_qwskincache;
270 static int r_qwskincache_size;
272 /// vertex coordinates for a quad that covers the screen exactly
273 extern const float r_screenvertex3f[12];
274 extern const float r_d3dscreenvertex3f[12];
275 const float r_screenvertex3f[12] =
282 const float r_d3dscreenvertex3f[12] =
290 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
293 for (i = 0;i < verts;i++)
304 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
307 for (i = 0;i < verts;i++)
317 // FIXME: move this to client?
320 if (gamemode == GAME_NEHAHRA)
322 Cvar_Set("gl_fogenable", "0");
323 Cvar_Set("gl_fogdensity", "0.2");
324 Cvar_Set("gl_fogred", "0.3");
325 Cvar_Set("gl_foggreen", "0.3");
326 Cvar_Set("gl_fogblue", "0.3");
328 r_refdef.fog_density = 0;
329 r_refdef.fog_red = 0;
330 r_refdef.fog_green = 0;
331 r_refdef.fog_blue = 0;
332 r_refdef.fog_alpha = 1;
333 r_refdef.fog_start = 0;
334 r_refdef.fog_end = 16384;
335 r_refdef.fog_height = 1<<30;
336 r_refdef.fog_fadedepth = 128;
337 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
340 static void R_BuildBlankTextures(void)
342 unsigned char data[4];
343 data[2] = 128; // normal X
344 data[1] = 128; // normal Y
345 data[0] = 255; // normal Z
346 data[3] = 128; // height
347 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
352 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
357 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
362 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
365 static void R_BuildNoTexture(void)
368 unsigned char pix[16][16][4];
369 // this makes a light grey/dark grey checkerboard texture
370 for (y = 0;y < 16;y++)
372 for (x = 0;x < 16;x++)
374 if ((y < 8) ^ (x < 8))
390 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
393 static void R_BuildWhiteCube(void)
395 unsigned char data[6*1*1*4];
396 memset(data, 255, sizeof(data));
397 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
400 static void R_BuildNormalizationCube(void)
404 vec_t s, t, intensity;
407 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
408 for (side = 0;side < 6;side++)
410 for (y = 0;y < NORMSIZE;y++)
412 for (x = 0;x < NORMSIZE;x++)
414 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
415 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
450 intensity = 127.0f / sqrt(DotProduct(v, v));
451 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
452 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
453 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
454 data[((side*64+y)*64+x)*4+3] = 255;
458 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
462 static void R_BuildFogTexture(void)
466 unsigned char data1[FOGWIDTH][4];
467 //unsigned char data2[FOGWIDTH][4];
470 r_refdef.fogmasktable_start = r_refdef.fog_start;
471 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
472 r_refdef.fogmasktable_range = r_refdef.fogrange;
473 r_refdef.fogmasktable_density = r_refdef.fog_density;
475 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
476 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
478 d = (x * r - r_refdef.fogmasktable_start);
479 if(developer_extra.integer)
480 Con_DPrintf("%f ", d);
482 if (r_fog_exp2.integer)
483 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
485 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
486 if(developer_extra.integer)
487 Con_DPrintf(" : %f ", alpha);
488 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
489 if(developer_extra.integer)
490 Con_DPrintf(" = %f\n", alpha);
491 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
494 for (x = 0;x < FOGWIDTH;x++)
496 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
501 //data2[x][0] = 255 - b;
502 //data2[x][1] = 255 - b;
503 //data2[x][2] = 255 - b;
506 if (r_texture_fogattenuation)
508 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
509 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
513 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
514 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
518 static void R_BuildFogHeightTexture(void)
520 unsigned char *inpixels;
528 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
529 if (r_refdef.fogheighttexturename[0])
530 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
533 r_refdef.fog_height_tablesize = 0;
534 if (r_texture_fogheighttexture)
535 R_FreeTexture(r_texture_fogheighttexture);
536 r_texture_fogheighttexture = NULL;
537 if (r_refdef.fog_height_table2d)
538 Mem_Free(r_refdef.fog_height_table2d);
539 r_refdef.fog_height_table2d = NULL;
540 if (r_refdef.fog_height_table1d)
541 Mem_Free(r_refdef.fog_height_table1d);
542 r_refdef.fog_height_table1d = NULL;
546 r_refdef.fog_height_tablesize = size;
547 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
548 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
549 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
551 // LordHavoc: now the magic - what is that table2d for? it is a cooked
552 // average fog color table accounting for every fog layer between a point
553 // and the camera. (Note: attenuation is handled separately!)
554 for (y = 0;y < size;y++)
556 for (x = 0;x < size;x++)
562 for (j = x;j <= y;j++)
564 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
570 for (j = x;j >= y;j--)
572 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
577 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
578 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
579 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
580 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
583 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
586 //=======================================================================================================================================================
588 static const char *builtinshaderstring =
589 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
590 "// written by Forest 'LordHavoc' Hale\n"
591 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
593 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
596 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
597 "#define USELIGHTMAP\n"
599 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
600 "#define USEEYEVECTOR\n"
603 "#ifdef USESHADOWMAP2D\n"
604 "# ifdef GL_EXT_gpu_shader4\n"
605 "# extension GL_EXT_gpu_shader4 : enable\n"
607 "# ifdef GL_ARB_texture_gather\n"
608 "# extension GL_ARB_texture_gather : enable\n"
610 "# ifdef GL_AMD_texture_texture4\n"
611 "# extension GL_AMD_texture_texture4 : enable\n"
616 "//#ifdef USESHADOWSAMPLER\n"
617 "//# extension GL_ARB_shadow : enable\n"
620 "//#ifdef __GLSL_CG_DATA_TYPES\n"
621 "//# define myhalf half\n"
622 "//# define myhalf2 half2\n"
623 "//# define myhalf3 half3\n"
624 "//# define myhalf4 half4\n"
626 "# define myhalf float\n"
627 "# define myhalf2 vec2\n"
628 "# define myhalf3 vec3\n"
629 "# define myhalf4 vec4\n"
632 "#ifdef VERTEX_SHADER\n"
633 "uniform mat4 ModelViewProjectionMatrix;\n"
636 "#ifdef MODE_DEPTH_OR_SHADOW\n"
637 "#ifdef VERTEX_SHADER\n"
640 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
643 "#else // !MODE_DEPTH_ORSHADOW\n"
648 "#ifdef MODE_SHOWDEPTH\n"
649 "#ifdef VERTEX_SHADER\n"
652 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
653 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
657 "#ifdef FRAGMENT_SHADER\n"
660 " gl_FragColor = gl_Color;\n"
663 "#else // !MODE_SHOWDEPTH\n"
668 "#ifdef MODE_POSTPROCESS\n"
669 "varying vec2 TexCoord1;\n"
670 "varying vec2 TexCoord2;\n"
672 "#ifdef VERTEX_SHADER\n"
675 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
676 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
678 " TexCoord2 = gl_MultiTexCoord4.xy;\n"
683 "#ifdef FRAGMENT_SHADER\n"
684 "uniform sampler2D Texture_First;\n"
686 "uniform sampler2D Texture_Second;\n"
687 "uniform vec4 BloomColorSubtract;\n"
689 "#ifdef USEGAMMARAMPS\n"
690 "uniform sampler2D Texture_GammaRamps;\n"
692 "#ifdef USESATURATION\n"
693 "uniform float Saturation;\n"
695 "#ifdef USEVIEWTINT\n"
696 "uniform vec4 ViewTintColor;\n"
698 "//uncomment these if you want to use them:\n"
699 "uniform vec4 UserVec1;\n"
700 "uniform vec4 UserVec2;\n"
701 "// uniform vec4 UserVec3;\n"
702 "// uniform vec4 UserVec4;\n"
703 "// uniform float ClientTime;\n"
704 "uniform vec2 PixelSize;\n"
707 " gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
709 " gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
711 "#ifdef USEVIEWTINT\n"
712 " gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
715 "#ifdef USEPOSTPROCESSING\n"
716 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
717 "// 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"
718 " float sobel = 1.0;\n"
719 " // vec2 ts = textureSize(Texture_First, 0);\n"
720 " // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
721 " vec2 px = PixelSize;\n"
722 " vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
723 " vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, 0.0)).rgb;\n"
724 " vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
725 " vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
726 " vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x, 0.0)).rgb;\n"
727 " vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
728 " vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
729 " vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2( 0.0,-px.y)).rgb;\n"
730 " vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
731 " vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
732 " vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2( 0.0, px.y)).rgb;\n"
733 " vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
734 " float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
735 " float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
736 " float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
737 " float px4 = 1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
738 " float px5 = 2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
739 " float px6 = 1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
740 " float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
741 " float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
742 " float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
743 " float py4 = 1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
744 " float py5 = 2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
745 " float py6 = 1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
746 " sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
747 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
748 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
749 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
750 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
751 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
752 " gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
753 " gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
756 "#ifdef USESATURATION\n"
757 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
758 " float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
759 " // 'vampire sight' effect, wheres red is compensated\n"
760 " #ifdef SATURATION_REDCOMPENSATE\n"
761 " float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
762 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
763 " gl_FragColor.r += rboost;\n"
765 " // normal desaturation\n"
766 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
767 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
771 "#ifdef USEGAMMARAMPS\n"
772 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
773 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
774 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
778 "#else // !MODE_POSTPROCESS\n"
783 "#ifdef MODE_GENERIC\n"
784 "#ifdef USEDIFFUSE\n"
785 "varying vec2 TexCoord1;\n"
787 "#ifdef USESPECULAR\n"
788 "varying vec2 TexCoord2;\n"
790 "#ifdef VERTEX_SHADER\n"
793 " gl_FrontColor = gl_Color;\n"
794 "#ifdef USEDIFFUSE\n"
795 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
797 "#ifdef USESPECULAR\n"
798 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
800 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
804 "#ifdef FRAGMENT_SHADER\n"
805 "#ifdef USEDIFFUSE\n"
806 "uniform sampler2D Texture_First;\n"
808 "#ifdef USESPECULAR\n"
809 "uniform sampler2D Texture_Second;\n"
814 "#ifdef USEVIEWTINT\n"
815 " gl_FragColor = gl_Color;\n"
817 " gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
819 "#ifdef USEDIFFUSE\n"
820 " gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
823 "#ifdef USESPECULAR\n"
824 " vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
825 "# ifdef USECOLORMAPPING\n"
826 " gl_FragColor *= tex2;\n"
829 " gl_FragColor += tex2;\n"
831 "# ifdef USEVERTEXTEXTUREBLEND\n"
832 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
837 "#else // !MODE_GENERIC\n"
842 "#ifdef MODE_BLOOMBLUR\n"
843 "varying TexCoord;\n"
844 "#ifdef VERTEX_SHADER\n"
847 " gl_FrontColor = gl_Color;\n"
848 " TexCoord = gl_MultiTexCoord0.xy;\n"
849 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
853 "#ifdef FRAGMENT_SHADER\n"
854 "uniform sampler2D Texture_First;\n"
855 "uniform vec4 BloomBlur_Parameters;\n"
860 " vec2 tc = TexCoord;\n"
861 " vec3 color = texture2D(Texture_First, tc).rgb;\n"
862 " tc += BloomBlur_Parameters.xy;\n"
863 " for (i = 1;i < SAMPLES;i++)\n"
865 " color += texture2D(Texture_First, tc).rgb;\n"
866 " tc += BloomBlur_Parameters.xy;\n"
868 " gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
871 "#else // !MODE_BLOOMBLUR\n"
872 "#ifdef MODE_REFRACTION\n"
873 "varying vec2 TexCoord;\n"
874 "varying vec4 ModelViewProjectionPosition;\n"
875 "uniform mat4 TexMatrix;\n"
876 "#ifdef VERTEX_SHADER\n"
880 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
881 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
882 " ModelViewProjectionPosition = gl_Position;\n"
886 "#ifdef FRAGMENT_SHADER\n"
887 "uniform sampler2D Texture_Normal;\n"
888 "uniform sampler2D Texture_Refraction;\n"
889 "uniform sampler2D Texture_Reflection;\n"
891 "uniform vec4 DistortScaleRefractReflect;\n"
892 "uniform vec4 ScreenScaleRefractReflect;\n"
893 "uniform vec4 ScreenCenterRefractReflect;\n"
894 "uniform vec4 RefractColor;\n"
895 "uniform vec4 ReflectColor;\n"
896 "uniform float ReflectFactor;\n"
897 "uniform float ReflectOffset;\n"
901 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
902 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
903 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
904 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
905 " // FIXME temporary hack to detect the case that the reflection\n"
906 " // gets blackened at edges due to leaving the area that contains actual\n"
908 " // Remove this 'ack once we have a better way to stop this thing from\n"
910 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
911 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
912 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
913 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
914 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
915 " gl_FragColor = vec4(texture2D(Texture_Refraction, ScreenTexCoord).rgb, 1.0) * RefractColor;\n"
918 "#else // !MODE_REFRACTION\n"
923 "#ifdef MODE_WATER\n"
924 "varying vec2 TexCoord;\n"
925 "varying vec3 EyeVector;\n"
926 "varying vec4 ModelViewProjectionPosition;\n"
927 "#ifdef VERTEX_SHADER\n"
928 "uniform vec3 EyePosition;\n"
929 "uniform mat4 TexMatrix;\n"
933 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
934 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
935 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
936 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
937 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
938 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
939 " ModelViewProjectionPosition = gl_Position;\n"
943 "#ifdef FRAGMENT_SHADER\n"
944 "uniform sampler2D Texture_Normal;\n"
945 "uniform sampler2D Texture_Refraction;\n"
946 "uniform sampler2D Texture_Reflection;\n"
948 "uniform vec4 DistortScaleRefractReflect;\n"
949 "uniform vec4 ScreenScaleRefractReflect;\n"
950 "uniform vec4 ScreenCenterRefractReflect;\n"
951 "uniform vec4 RefractColor;\n"
952 "uniform vec4 ReflectColor;\n"
953 "uniform float ReflectFactor;\n"
954 "uniform float ReflectOffset;\n"
955 "uniform float ClientTime;\n"
956 "#ifdef USENORMALMAPSCROLLBLEND\n"
957 "uniform vec2 NormalmapScrollBlend;\n"
962 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
963 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
964 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
965 " //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
966 " // slight water animation via 2 layer scrolling (todo: tweak)\n"
967 " #ifdef USENORMALMAPSCROLLBLEND\n"
968 " vec3 normal = texture2D(Texture_Normal, (TexCoord + vec2(0.08, 0.08)*ClientTime*NormalmapScrollBlend.x*0.5)*NormalmapScrollBlend.y).rgb - vec3(1.0);\n"
969 " normal += texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime*NormalmapScrollBlend.x)*NormalmapScrollBlend.y*0.75).rgb;\n"
970 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(normal) + vec3(0.15)).xyxy * DistortScaleRefractReflect;\n"
972 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
974 " // FIXME temporary hack to detect the case that the reflection\n"
975 " // gets blackened at edges due to leaving the area that contains actual\n"
977 " // Remove this 'ack once we have a better way to stop this thing from\n"
979 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, 0.01)).rgb) / 0.002);\n"
980 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, -0.01)).rgb) / 0.002);\n"
981 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, 0.01)).rgb) / 0.002);\n"
982 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, -0.01)).rgb) / 0.002);\n"
983 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
984 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, 0.005)).rgb) / 0.002);\n"
985 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, -0.005)).rgb) / 0.002);\n"
986 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, 0.005)).rgb) / 0.002);\n"
987 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, -0.005)).rgb) / 0.002);\n"
988 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
989 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
990 " gl_FragColor = mix(vec4(texture2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, vec4(texture2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
993 "#else // !MODE_WATER\n"
998 "// common definitions between vertex shader and fragment shader:\n"
1000 "varying vec2 TexCoord;\n"
1001 "#ifdef USEVERTEXTEXTUREBLEND\n"
1002 "varying vec2 TexCoord2;\n"
1004 "#ifdef USELIGHTMAP\n"
1005 "varying vec2 TexCoordLightmap;\n"
1008 "#ifdef MODE_LIGHTSOURCE\n"
1009 "varying vec3 CubeVector;\n"
1012 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
1013 "varying vec3 LightVector;\n"
1016 "#ifdef USEEYEVECTOR\n"
1017 "varying vec3 EyeVector;\n"
1020 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
1023 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
1024 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
1025 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
1026 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
1029 "#ifdef USEREFLECTION\n"
1030 "varying vec4 ModelViewProjectionPosition;\n"
1032 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1033 "uniform vec3 LightPosition;\n"
1034 "varying vec4 ModelViewPosition;\n"
1037 "#ifdef MODE_LIGHTSOURCE\n"
1038 "uniform vec3 LightPosition;\n"
1040 "uniform vec3 EyePosition;\n"
1041 "#ifdef MODE_LIGHTDIRECTION\n"
1042 "uniform vec3 LightDir;\n"
1044 "uniform vec4 FogPlane;\n"
1046 "#ifdef USESHADOWMAPORTHO\n"
1047 "varying vec3 ShadowMapTC;\n"
1054 "// 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"
1056 "// fragment shader specific:\n"
1057 "#ifdef FRAGMENT_SHADER\n"
1059 "uniform sampler2D Texture_Normal;\n"
1060 "uniform sampler2D Texture_Color;\n"
1061 "uniform sampler2D Texture_Gloss;\n"
1063 "uniform sampler2D Texture_Glow;\n"
1065 "#ifdef USEVERTEXTEXTUREBLEND\n"
1066 "uniform sampler2D Texture_SecondaryNormal;\n"
1067 "uniform sampler2D Texture_SecondaryColor;\n"
1068 "uniform sampler2D Texture_SecondaryGloss;\n"
1070 "uniform sampler2D Texture_SecondaryGlow;\n"
1073 "#ifdef USECOLORMAPPING\n"
1074 "uniform sampler2D Texture_Pants;\n"
1075 "uniform sampler2D Texture_Shirt;\n"
1078 "#ifdef USEFOGHEIGHTTEXTURE\n"
1079 "uniform sampler2D Texture_FogHeightTexture;\n"
1081 "uniform sampler2D Texture_FogMask;\n"
1083 "#ifdef USELIGHTMAP\n"
1084 "uniform sampler2D Texture_Lightmap;\n"
1086 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1087 "uniform sampler2D Texture_Deluxemap;\n"
1089 "#ifdef USEREFLECTION\n"
1090 "uniform sampler2D Texture_Reflection;\n"
1093 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1094 "uniform sampler2D Texture_ScreenDepth;\n"
1095 "uniform sampler2D Texture_ScreenNormalMap;\n"
1097 "#ifdef USEDEFERREDLIGHTMAP\n"
1098 "uniform sampler2D Texture_ScreenDiffuse;\n"
1099 "uniform sampler2D Texture_ScreenSpecular;\n"
1102 "uniform myhalf3 Color_Pants;\n"
1103 "uniform myhalf3 Color_Shirt;\n"
1104 "uniform myhalf3 FogColor;\n"
1107 "uniform float FogRangeRecip;\n"
1108 "uniform float FogPlaneViewDist;\n"
1109 "uniform float FogHeightFade;\n"
1110 "vec3 FogVertex(vec3 surfacecolor)\n"
1112 " vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1113 " float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1115 "#ifdef USEFOGHEIGHTTEXTURE\n"
1116 " vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1117 " fogfrac = fogheightpixel.a;\n"
1118 " return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1120 "# ifdef USEFOGOUTSIDE\n"
1121 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1123 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1125 " return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1130 "#ifdef USEOFFSETMAPPING\n"
1131 "uniform float OffsetMapping_Scale;\n"
1132 "vec2 OffsetMapping(vec2 TexCoord)\n"
1134 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1135 " // 14 sample relief mapping: linear search and then binary search\n"
1136 " // this basically steps forward a small amount repeatedly until it finds\n"
1137 " // itself inside solid, then jitters forward and back using decreasing\n"
1138 " // amounts to find the impact\n"
1139 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1140 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1141 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1142 " vec3 RT = vec3(TexCoord, 1);\n"
1143 " OffsetVector *= 0.1;\n"
1144 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1145 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1146 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1147 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1148 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1149 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1150 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1151 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1152 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1153 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
1154 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
1155 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
1156 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
1157 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1160 " // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1161 " // this basically moves forward the full distance, and then backs up based\n"
1162 " // on height of samples\n"
1163 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1164 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1165 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1166 " TexCoord += OffsetVector;\n"
1167 " OffsetVector *= 0.5;\n"
1168 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1169 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1170 " return TexCoord;\n"
1173 "#endif // USEOFFSETMAPPING\n"
1175 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1176 "uniform sampler2D Texture_Attenuation;\n"
1177 "uniform samplerCube Texture_Cube;\n"
1180 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1182 "#ifdef USESHADOWMAP2D\n"
1183 "# ifdef USESHADOWSAMPLER\n"
1184 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1186 "uniform sampler2D Texture_ShadowMap2D;\n"
1190 "#ifdef USESHADOWMAPVSDCT\n"
1191 "uniform samplerCube Texture_CubeProjection;\n"
1194 "#if defined(USESHADOWMAP2D)\n"
1195 "uniform vec2 ShadowMap_TextureScale;\n"
1196 "uniform vec4 ShadowMap_Parameters;\n"
1199 "#if defined(USESHADOWMAP2D)\n"
1200 "# ifdef USESHADOWMAPORTHO\n"
1201 "# define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1203 "# ifdef USESHADOWMAPVSDCT\n"
1204 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1206 " vec3 adir = abs(dir);\n"
1207 " vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1208 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1209 " return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1212 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1214 " vec3 adir = abs(dir);\n"
1215 " float ma = adir.z;\n"
1216 " vec4 proj = vec4(dir, 2.5);\n"
1217 " if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1218 " if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1219 " vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1220 " 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"
1224 "#endif // defined(USESHADOWMAP2D)\n"
1226 "# ifdef USESHADOWMAP2D\n"
1227 "float ShadowMapCompare(vec3 dir)\n"
1229 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1232 "# ifdef USESHADOWSAMPLER\n"
1233 "# ifdef USESHADOWMAPPCF\n"
1234 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1235 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1236 " 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"
1238 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1241 "# ifdef USESHADOWMAPPCF\n"
1242 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1243 "# ifdef GL_ARB_texture_gather\n"
1244 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1246 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1248 " vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1249 "# if USESHADOWMAPPCF > 1\n"
1250 " vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1251 " vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1252 " vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1253 " vec4 group4 = step(shadowmaptc.z, texval(-2.0, 0.0));\n"
1254 " vec4 group5 = step(shadowmaptc.z, texval( 0.0, 0.0));\n"
1255 " vec4 group6 = step(shadowmaptc.z, texval( 2.0, 0.0));\n"
1256 " vec4 group7 = step(shadowmaptc.z, texval(-2.0, 2.0));\n"
1257 " vec4 group8 = step(shadowmaptc.z, texval( 0.0, 2.0));\n"
1258 " vec4 group9 = step(shadowmaptc.z, texval( 2.0, 2.0));\n"
1259 " vec4 locols = vec4(group1.ab, group3.ab);\n"
1260 " vec4 hicols = vec4(group7.rg, group9.rg);\n"
1261 " locols.yz += group2.ab;\n"
1262 " hicols.yz += group8.rg;\n"
1263 " vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1264 " vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1265 " mix(locols, hicols, offset.y);\n"
1266 " vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1267 " cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1268 " f = dot(cols, vec4(1.0/25.0));\n"
1270 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1271 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1272 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1273 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1274 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1275 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1276 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1279 "# ifdef GL_EXT_gpu_shader4\n"
1280 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1282 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1284 "# if USESHADOWMAPPCF > 1\n"
1285 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1286 " center *= ShadowMap_TextureScale;\n"
1287 " 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"
1288 " 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"
1289 " 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"
1290 " 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"
1291 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1292 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1294 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1295 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1296 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1297 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1298 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1299 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1303 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1306 "# ifdef USESHADOWMAPORTHO\n"
1307 " return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1313 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1314 "#endif // FRAGMENT_SHADER\n"
1319 "#ifdef MODE_DEFERREDGEOMETRY\n"
1320 "#ifdef VERTEX_SHADER\n"
1321 "uniform mat4 TexMatrix;\n"
1322 "#ifdef USEVERTEXTEXTUREBLEND\n"
1323 "uniform mat4 BackgroundTexMatrix;\n"
1325 "uniform mat4 ModelViewMatrix;\n"
1328 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1329 "#ifdef USEVERTEXTEXTUREBLEND\n"
1330 " gl_FrontColor = gl_Color;\n"
1331 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1334 " // transform unnormalized eye direction into tangent space\n"
1335 "#ifdef USEOFFSETMAPPING\n"
1336 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1337 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1338 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1339 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1342 " VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1343 " VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1344 " VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1345 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1347 "#endif // VERTEX_SHADER\n"
1349 "#ifdef FRAGMENT_SHADER\n"
1352 "#ifdef USEOFFSETMAPPING\n"
1353 " // apply offsetmapping\n"
1354 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1355 "#define TexCoord TexCoordOffset\n"
1358 "#ifdef USEALPHAKILL\n"
1359 " if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1363 "#ifdef USEVERTEXTEXTUREBLEND\n"
1364 " float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1365 " float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1366 " //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1367 " //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1370 "#ifdef USEVERTEXTEXTUREBLEND\n"
1371 " vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1372 " float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1374 " vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1375 " float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1378 " gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1380 "#endif // FRAGMENT_SHADER\n"
1381 "#else // !MODE_DEFERREDGEOMETRY\n"
1386 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1387 "#ifdef VERTEX_SHADER\n"
1388 "uniform mat4 ModelViewMatrix;\n"
1391 " ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1392 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1394 "#endif // VERTEX_SHADER\n"
1396 "#ifdef FRAGMENT_SHADER\n"
1397 "uniform mat4 ViewToLight;\n"
1398 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1399 "uniform vec2 ScreenToDepth;\n"
1400 "uniform myhalf3 DeferredColor_Ambient;\n"
1401 "uniform myhalf3 DeferredColor_Diffuse;\n"
1402 "#ifdef USESPECULAR\n"
1403 "uniform myhalf3 DeferredColor_Specular;\n"
1404 "uniform myhalf SpecularPower;\n"
1406 "uniform myhalf2 PixelToScreenTexCoord;\n"
1409 " // calculate viewspace pixel position\n"
1410 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1412 " position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1413 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1414 " // decode viewspace pixel normal\n"
1415 " myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1416 " myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1417 " // surfacenormal = pixel normal in viewspace\n"
1418 " // LightVector = pixel to light in viewspace\n"
1419 " // CubeVector = position in lightspace\n"
1420 " // eyevector = pixel to view in viewspace\n"
1421 " vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1422 " myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1423 "#ifdef USEDIFFUSE\n"
1424 " // calculate diffuse shading\n"
1425 " myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1426 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1428 "#ifdef USESPECULAR\n"
1429 " // calculate directional shading\n"
1430 " vec3 eyevector = position * -1.0;\n"
1431 "# ifdef USEEXACTSPECULARMATH\n"
1432 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1434 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1435 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1439 "#if defined(USESHADOWMAP2D)\n"
1440 " fade *= ShadowMapCompare(CubeVector);\n"
1443 "#ifdef USEDIFFUSE\n"
1444 " gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1446 " gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1448 "#ifdef USESPECULAR\n"
1449 " gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1451 " gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1454 "# ifdef USECUBEFILTER\n"
1455 " vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1456 " gl_FragData[0].rgb *= cubecolor;\n"
1457 " gl_FragData[1].rgb *= cubecolor;\n"
1460 "#endif // FRAGMENT_SHADER\n"
1461 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1466 "#ifdef VERTEX_SHADER\n"
1467 "uniform mat4 TexMatrix;\n"
1468 "#ifdef USEVERTEXTEXTUREBLEND\n"
1469 "uniform mat4 BackgroundTexMatrix;\n"
1471 "#ifdef MODE_LIGHTSOURCE\n"
1472 "uniform mat4 ModelToLight;\n"
1474 "#ifdef USESHADOWMAPORTHO\n"
1475 "uniform mat4 ShadowMapMatrix;\n"
1479 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1480 " gl_FrontColor = gl_Color;\n"
1482 " // copy the surface texcoord\n"
1483 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1484 "#ifdef USEVERTEXTEXTUREBLEND\n"
1485 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1487 "#ifdef USELIGHTMAP\n"
1488 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1491 "#ifdef MODE_LIGHTSOURCE\n"
1492 " // transform vertex position into light attenuation/cubemap space\n"
1493 " // (-1 to +1 across the light box)\n"
1494 " CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1496 "# ifdef USEDIFFUSE\n"
1497 " // transform unnormalized light direction into tangent space\n"
1498 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
1499 " // normalize it per pixel)\n"
1500 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1501 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1502 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1503 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1507 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1508 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1509 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1510 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1513 " // transform unnormalized eye direction into tangent space\n"
1514 "#ifdef USEEYEVECTOR\n"
1515 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1516 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1517 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1518 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1522 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1523 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1526 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1527 " VectorS = gl_MultiTexCoord1.xyz;\n"
1528 " VectorT = gl_MultiTexCoord2.xyz;\n"
1529 " VectorR = gl_MultiTexCoord3.xyz;\n"
1532 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1533 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1535 "#ifdef USESHADOWMAPORTHO\n"
1536 " ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1539 "#ifdef USEREFLECTION\n"
1540 " ModelViewProjectionPosition = gl_Position;\n"
1543 "#endif // VERTEX_SHADER\n"
1548 "#ifdef FRAGMENT_SHADER\n"
1549 "#ifdef USEDEFERREDLIGHTMAP\n"
1550 "uniform myhalf2 PixelToScreenTexCoord;\n"
1551 "uniform myhalf3 DeferredMod_Diffuse;\n"
1552 "uniform myhalf3 DeferredMod_Specular;\n"
1554 "uniform myhalf3 Color_Ambient;\n"
1555 "uniform myhalf3 Color_Diffuse;\n"
1556 "uniform myhalf3 Color_Specular;\n"
1557 "uniform myhalf SpecularPower;\n"
1559 "uniform myhalf3 Color_Glow;\n"
1561 "uniform myhalf Alpha;\n"
1562 "#ifdef USEREFLECTION\n"
1563 "uniform vec4 DistortScaleRefractReflect;\n"
1564 "uniform vec4 ScreenScaleRefractReflect;\n"
1565 "uniform vec4 ScreenCenterRefractReflect;\n"
1566 "uniform myhalf4 ReflectColor;\n"
1568 "#ifdef USEREFLECTCUBE\n"
1569 "uniform mat4 ModelToReflectCube;\n"
1570 "uniform sampler2D Texture_ReflectMask;\n"
1571 "uniform samplerCube Texture_ReflectCube;\n"
1573 "#ifdef MODE_LIGHTDIRECTION\n"
1574 "uniform myhalf3 LightColor;\n"
1576 "#ifdef MODE_LIGHTSOURCE\n"
1577 "uniform myhalf3 LightColor;\n"
1581 "#ifdef USEOFFSETMAPPING\n"
1582 " // apply offsetmapping\n"
1583 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1584 "#define TexCoord TexCoordOffset\n"
1587 " // combine the diffuse textures (base, pants, shirt)\n"
1588 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1589 "#ifdef USEALPHAKILL\n"
1590 " if (color.a < 0.5)\n"
1593 " color.a *= Alpha;\n"
1594 "#ifdef USECOLORMAPPING\n"
1595 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1597 "#ifdef USEVERTEXTEXTUREBLEND\n"
1598 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1599 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1600 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1601 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1603 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1606 " // get the surface normal\n"
1607 "#ifdef USEVERTEXTEXTUREBLEND\n"
1608 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1610 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1613 " // get the material colors\n"
1614 " myhalf3 diffusetex = color.rgb;\n"
1615 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1616 "# ifdef USEVERTEXTEXTUREBLEND\n"
1617 " myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1619 " myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1623 "#ifdef USEREFLECTCUBE\n"
1624 " vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1625 " vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1626 " vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1627 " diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1633 "#ifdef MODE_LIGHTSOURCE\n"
1634 " // light source\n"
1635 "#ifdef USEDIFFUSE\n"
1636 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1637 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1638 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1639 "#ifdef USESPECULAR\n"
1640 "#ifdef USEEXACTSPECULARMATH\n"
1641 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1643 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1644 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1646 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1649 " color.rgb = diffusetex * Color_Ambient;\n"
1651 " color.rgb *= LightColor;\n"
1652 " color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1653 "#if defined(USESHADOWMAP2D)\n"
1654 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1656 "# ifdef USECUBEFILTER\n"
1657 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1659 "#endif // MODE_LIGHTSOURCE\n"
1664 "#ifdef MODE_LIGHTDIRECTION\n"
1666 "#ifdef USEDIFFUSE\n"
1667 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1669 "#define lightcolor LightColor\n"
1670 "#endif // MODE_LIGHTDIRECTION\n"
1671 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1673 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1674 " myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1675 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1676 " // convert modelspace light vector to tangentspace\n"
1677 " myhalf3 lightnormal;\n"
1678 " lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1679 " lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1680 " lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1681 " lightnormal = normalize(lightnormal); // VectorS/T/R are not always perfectly normalized, and EXACTSPECULARMATH is very picky about this\n"
1682 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1683 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1684 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1685 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1686 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1687 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1688 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1689 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1690 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1691 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1692 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1693 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1695 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1696 " myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1697 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1703 "#ifdef MODE_FAKELIGHT\n"
1705 "myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
1706 "myhalf3 lightcolor = myhalf3(1.0);\n"
1707 "#endif // MODE_FAKELIGHT\n"
1712 "#ifdef MODE_LIGHTMAP\n"
1713 " color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1714 "#endif // MODE_LIGHTMAP\n"
1715 "#ifdef MODE_VERTEXCOLOR\n"
1716 " color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1717 "#endif // MODE_VERTEXCOLOR\n"
1718 "#ifdef MODE_FLATCOLOR\n"
1719 " color.rgb = diffusetex * Color_Ambient;\n"
1720 "#endif // MODE_FLATCOLOR\n"
1726 "# ifdef USEDIFFUSE\n"
1727 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1728 "# ifdef USESPECULAR\n"
1729 "# ifdef USEEXACTSPECULARMATH\n"
1730 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1732 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1733 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1735 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1737 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1740 " color.rgb = diffusetex * Color_Ambient;\n"
1744 "#ifdef USESHADOWMAPORTHO\n"
1745 " color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1748 "#ifdef USEDEFERREDLIGHTMAP\n"
1749 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1750 " color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1751 " color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1755 "#ifdef USEVERTEXTEXTUREBLEND\n"
1756 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1758 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1763 " color.rgb = FogVertex(color.rgb);\n"
1766 " // 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"
1767 "#ifdef USEREFLECTION\n"
1768 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1769 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1770 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1771 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1772 " // FIXME temporary hack to detect the case that the reflection\n"
1773 " // gets blackened at edges due to leaving the area that contains actual\n"
1775 " // Remove this 'ack once we have a better way to stop this thing from\n"
1777 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1778 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1779 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1780 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1781 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1782 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1785 " gl_FragColor = vec4(color);\n"
1787 "#endif // FRAGMENT_SHADER\n"
1789 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1790 "#endif // !MODE_DEFERREDGEOMETRY\n"
1791 "#endif // !MODE_WATER\n"
1792 "#endif // !MODE_REFRACTION\n"
1793 "#endif // !MODE_BLOOMBLUR\n"
1794 "#endif // !MODE_GENERIC\n"
1795 "#endif // !MODE_POSTPROCESS\n"
1796 "#endif // !MODE_SHOWDEPTH\n"
1797 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1801 =========================================================================================================================================================
1805 =========================================================================================================================================================
1809 =========================================================================================================================================================
1813 =========================================================================================================================================================
1817 =========================================================================================================================================================
1821 =========================================================================================================================================================
1825 =========================================================================================================================================================
1828 const char *builtincgshaderstring =
1829 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1830 "// written by Forest 'LordHavoc' Hale\n"
1831 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1833 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1834 "#if defined(USEREFLECTION)\n"
1835 "#undef USESHADOWMAPORTHO\n"
1838 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1841 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1842 "#define USELIGHTMAP\n"
1844 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
1845 "#define USEEYEVECTOR\n"
1848 "#ifdef FRAGMENT_SHADER\n"
1850 "//#undef USESHADOWMAPPCF\n"
1851 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1852 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1854 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1858 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1859 "#ifdef VERTEX_SHADER\n"
1862 "float4 gl_Vertex : POSITION,\n"
1863 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1864 "out float4 gl_Position : POSITION,\n"
1865 "out float Depth : TEXCOORD0\n"
1868 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1869 " Depth = gl_Position.z;\n"
1873 "#ifdef FRAGMENT_SHADER\n"
1876 "float Depth : TEXCOORD0,\n"
1877 "out float4 gl_FragColor : COLOR\n"
1880 "// float4 temp = float4(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0),0.0);\n"
1881 " float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
1882 " temp.yz -= floor(temp.yz);\n"
1883 " gl_FragColor = temp;\n"
1884 "// gl_FragColor = float4(Depth,0,0,0);\n"
1887 "#else // !MODE_DEPTH_ORSHADOW\n"
1892 "#ifdef MODE_SHOWDEPTH\n"
1893 "#ifdef VERTEX_SHADER\n"
1896 "float4 gl_Vertex : POSITION,\n"
1897 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1898 "out float4 gl_Position : POSITION,\n"
1899 "out float4 gl_FrontColor : COLOR0\n"
1902 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1903 " gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1907 "#ifdef FRAGMENT_SHADER\n"
1910 "float4 gl_FrontColor : COLOR0,\n"
1911 "out float4 gl_FragColor : COLOR\n"
1914 " gl_FragColor = gl_FrontColor;\n"
1917 "#else // !MODE_SHOWDEPTH\n"
1922 "#ifdef MODE_POSTPROCESS\n"
1924 "#ifdef VERTEX_SHADER\n"
1927 "float4 gl_Vertex : POSITION,\n"
1928 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1929 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1930 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1931 "out float4 gl_Position : POSITION,\n"
1932 "out float2 TexCoord1 : TEXCOORD0,\n"
1933 "out float2 TexCoord2 : TEXCOORD1\n"
1936 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1937 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
1939 " TexCoord2 = gl_MultiTexCoord4.xy;\n"
1944 "#ifdef FRAGMENT_SHADER\n"
1947 "float2 TexCoord1 : TEXCOORD0,\n"
1948 "float2 TexCoord2 : TEXCOORD1,\n"
1949 "uniform sampler Texture_First : register(s0),\n"
1951 "uniform sampler Texture_Second : register(s1),\n"
1953 "#ifdef USEGAMMARAMPS\n"
1954 "uniform sampler Texture_GammaRamps : register(s2),\n"
1956 "#ifdef USESATURATION\n"
1957 "uniform float Saturation : register(c30),\n"
1959 "#ifdef USEVIEWTINT\n"
1960 "uniform float4 ViewTintColor : register(c41),\n"
1962 "uniform float4 UserVec1 : register(c37),\n"
1963 "uniform float4 UserVec2 : register(c38),\n"
1964 "uniform float4 UserVec3 : register(c39),\n"
1965 "uniform float4 UserVec4 : register(c40),\n"
1966 "uniform float ClientTime : register(c2),\n"
1967 "uniform float2 PixelSize : register(c25),\n"
1968 "uniform float4 BloomColorSubtract : register(c43),\n"
1969 "out float4 gl_FragColor : COLOR\n"
1972 " gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1974 " gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
1976 "#ifdef USEVIEWTINT\n"
1977 " gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1980 "#ifdef USEPOSTPROCESSING\n"
1981 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1982 "// 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"
1983 " float sobel = 1.0;\n"
1984 " // float2 ts = textureSize(Texture_First, 0);\n"
1985 " // float2 px = float2(1/ts.x, 1/ts.y);\n"
1986 " float2 px = PixelSize;\n"
1987 " float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1988 " float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x, 0.0)).rgb;\n"
1989 " float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1990 " float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1991 " float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x, 0.0)).rgb;\n"
1992 " float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1993 " float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1994 " float3 y2 = tex2D(Texture_First, TexCoord1 + float2( 0.0,-px.y)).rgb;\n"
1995 " float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1996 " float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1997 " float3 y5 = tex2D(Texture_First, TexCoord1 + float2( 0.0, px.y)).rgb;\n"
1998 " float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1999 " float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
2000 " float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
2001 " float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
2002 " float px4 = 1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
2003 " float px5 = 2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
2004 " float px6 = 1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
2005 " float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
2006 " float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
2007 " float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
2008 " float py4 = 1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
2009 " float py5 = 2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
2010 " float py6 = 1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
2011 " sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
2012 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2013 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2014 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2015 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107, 0.707107)) * UserVec1.y;\n"
2016 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990, 0.891007)) * UserVec1.y;\n"
2017 " gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2018 " gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2021 "#ifdef USESATURATION\n"
2022 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2023 " float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2024 " // 'vampire sight' effect, wheres red is compensated\n"
2025 " #ifdef SATURATION_REDCOMPENSATE\n"
2026 " float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
2027 " gl_FragColor.rgb = mix(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2028 " gl_FragColor.r += r;\n"
2030 " // normal desaturation\n"
2031 " //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2032 " gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2036 "#ifdef USEGAMMARAMPS\n"
2037 " gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2038 " gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2039 " gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2043 "#else // !MODE_POSTPROCESS\n"
2048 "#ifdef MODE_GENERIC\n"
2049 "#ifdef VERTEX_SHADER\n"
2052 "float4 gl_Vertex : POSITION,\n"
2053 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2054 "float4 gl_Color : COLOR0,\n"
2055 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2056 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2057 "out float4 gl_Position : POSITION,\n"
2058 "#ifdef USEDIFFUSE\n"
2059 "out float2 TexCoord1 : TEXCOORD0,\n"
2061 "#ifdef USESPECULAR\n"
2062 "out float2 TexCoord2 : TEXCOORD1,\n"
2064 "out float4 gl_FrontColor : COLOR\n"
2068 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2070 " gl_FrontColor = gl_Color; // Cg is forward\n"
2072 "#ifdef USEDIFFUSE\n"
2073 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
2075 "#ifdef USESPECULAR\n"
2076 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
2078 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2082 "#ifdef FRAGMENT_SHADER\n"
2086 "float4 gl_FrontColor : COLOR0,\n"
2087 "float2 TexCoord1 : TEXCOORD0,\n"
2088 "float2 TexCoord2 : TEXCOORD1,\n"
2089 "#ifdef USEDIFFUSE\n"
2090 "uniform sampler Texture_First : register(s0),\n"
2092 "#ifdef USESPECULAR\n"
2093 "uniform sampler Texture_Second : register(s1),\n"
2095 "out float4 gl_FragColor : COLOR\n"
2098 "#ifdef USEVIEWTINT\n"
2099 " gl_FragColor = gl_FrontColor;\n"
2101 " gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
2103 "#ifdef USEDIFFUSE\n"
2104 " gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2107 "#ifdef USESPECULAR\n"
2108 " float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2109 "# ifdef USECOLORMAPPING\n"
2110 " gl_FragColor *= tex2;\n"
2113 " gl_FragColor += tex2;\n"
2115 "# ifdef USEVERTEXTEXTUREBLEND\n"
2116 " gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2121 "#else // !MODE_GENERIC\n"
2126 "#ifdef MODE_BLOOMBLUR\n"
2127 "#ifdef VERTEX_SHADER\n"
2130 "float4 gl_Vertex : POSITION,\n"
2131 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2132 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2133 "out float4 gl_Position : POSITION,\n"
2134 "out float2 TexCoord : TEXCOORD0\n"
2137 " TexCoord = gl_MultiTexCoord0.xy;\n"
2138 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2142 "#ifdef FRAGMENT_SHADER\n"
2146 "float2 TexCoord : TEXCOORD0,\n"
2147 "uniform sampler Texture_First : register(s0),\n"
2148 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2149 "out float4 gl_FragColor : COLOR\n"
2153 " float2 tc = TexCoord;\n"
2154 " float3 color = tex2D(Texture_First, tc).rgb;\n"
2155 " tc += BloomBlur_Parameters.xy;\n"
2156 " for (i = 1;i < SAMPLES;i++)\n"
2158 " color += tex2D(Texture_First, tc).rgb;\n"
2159 " tc += BloomBlur_Parameters.xy;\n"
2161 " gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2164 "#else // !MODE_BLOOMBLUR\n"
2165 "#ifdef MODE_REFRACTION\n"
2166 "#ifdef VERTEX_SHADER\n"
2169 "float4 gl_Vertex : POSITION,\n"
2170 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2171 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2172 "uniform float4x4 TexMatrix : register(c0),\n"
2173 "uniform float3 EyePosition : register(c24),\n"
2174 "out float4 gl_Position : POSITION,\n"
2175 "out float2 TexCoord : TEXCOORD0,\n"
2176 "out float3 EyeVector : TEXCOORD1,\n"
2177 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2180 " TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2181 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2182 " ModelViewProjectionPosition = gl_Position;\n"
2186 "#ifdef FRAGMENT_SHADER\n"
2189 "float2 TexCoord : TEXCOORD0,\n"
2190 "float3 EyeVector : TEXCOORD1,\n"
2191 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2192 "uniform sampler Texture_Normal : register(s0),\n"
2193 "uniform sampler Texture_Refraction : register(s3),\n"
2194 "uniform sampler Texture_Reflection : register(s7),\n"
2195 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2196 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2197 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2198 "uniform float4 RefractColor : register(c29),\n"
2199 "out float4 gl_FragColor : COLOR\n"
2202 " float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2203 " //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"
2204 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2205 " float2 ScreenTexCoord = SafeScreenTexCoord + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy;\n"
2206 " // FIXME temporary hack to detect the case that the reflection\n"
2207 " // gets blackened at edges due to leaving the area that contains actual\n"
2209 " // Remove this 'ack once we have a better way to stop this thing from\n"
2211 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2212 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2213 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2214 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2215 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2216 " gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
2219 "#else // !MODE_REFRACTION\n"
2224 "#ifdef MODE_WATER\n"
2225 "#ifdef VERTEX_SHADER\n"
2229 "float4 gl_Vertex : POSITION,\n"
2230 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2231 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2232 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2233 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2234 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2235 "uniform float4x4 TexMatrix : register(c0),\n"
2236 "uniform float3 EyePosition : register(c24),\n"
2237 "out float4 gl_Position : POSITION,\n"
2238 "out float2 TexCoord : TEXCOORD0,\n"
2239 "out float3 EyeVector : TEXCOORD1,\n"
2240 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2243 " TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2244 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2245 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2246 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2247 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2248 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2249 " ModelViewProjectionPosition = gl_Position;\n"
2253 "#ifdef FRAGMENT_SHADER\n"
2256 "float2 TexCoord : TEXCOORD0,\n"
2257 "float3 EyeVector : TEXCOORD1,\n"
2258 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2259 "uniform sampler Texture_Normal : register(s0),\n"
2260 "uniform sampler Texture_Refraction : register(s3),\n"
2261 "uniform sampler Texture_Reflection : register(s7),\n"
2262 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2263 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2264 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2265 "uniform float4 RefractColor : register(c29),\n"
2266 "uniform float4 ReflectColor : register(c26),\n"
2267 "uniform float ReflectFactor : register(c27),\n"
2268 "uniform float ReflectOffset : register(c28),\n"
2269 "out float4 gl_FragColor : COLOR\n"
2272 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2273 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2274 " float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2275 " //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2276 " float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2277 " // FIXME temporary hack to detect the case that the reflection\n"
2278 " // gets blackened at edges due to leaving the area that contains actual\n"
2280 " // Remove this 'ack once we have a better way to stop this thing from\n"
2282 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2283 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2284 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2285 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2286 " ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2287 " f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2288 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2289 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2290 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2291 " ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2292 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2293 " gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
2296 "#else // !MODE_WATER\n"
2301 "// 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"
2303 "// fragment shader specific:\n"
2304 "#ifdef FRAGMENT_SHADER\n"
2307 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2310 "#ifdef USEFOGHEIGHTTEXTURE\n"
2311 " float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2312 " fogfrac = fogheightpixel.a;\n"
2313 " return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2315 "# ifdef USEFOGOUTSIDE\n"
2316 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2318 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2320 " return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2325 "#ifdef USEOFFSETMAPPING\n"
2326 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2328 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2329 " // 14 sample relief mapping: linear search and then binary search\n"
2330 " // this basically steps forward a small amount repeatedly until it finds\n"
2331 " // itself inside solid, then jitters forward and back using decreasing\n"
2332 " // amounts to find the impact\n"
2333 " //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2334 " //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2335 " float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2336 " float3 RT = float3(TexCoord, 1);\n"
2337 " OffsetVector *= 0.1;\n"
2338 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2339 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2340 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2341 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2342 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2343 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2344 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2345 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2346 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2347 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
2348 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
2349 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
2350 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
2351 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2354 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2355 " // this basically moves forward the full distance, and then backs up based\n"
2356 " // on height of samples\n"
2357 " //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2358 " //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2359 " float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2360 " TexCoord += OffsetVector;\n"
2361 " OffsetVector *= 0.333;\n"
2362 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2363 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2364 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2365 " return TexCoord;\n"
2368 "#endif // USEOFFSETMAPPING\n"
2370 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2371 "#if defined(USESHADOWMAP2D)\n"
2372 "# ifdef USESHADOWMAPORTHO\n"
2373 "# define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2375 "# ifdef USESHADOWMAPVSDCT\n"
2376 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2378 " float3 adir = abs(dir);\n"
2379 " float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2380 " float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2381 " return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2384 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2386 " float3 adir = abs(dir);\n"
2387 " float ma = adir.z;\n"
2388 " float4 proj = float4(dir, 2.5);\n"
2389 " if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2390 " if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2392 " 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"
2394 " float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2395 " 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"
2400 "#endif // defined(USESHADOWMAP2D)\n"
2402 "# ifdef USESHADOWMAP2D\n"
2403 "#ifdef USESHADOWMAPVSDCT\n"
2404 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2406 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2409 "#ifdef USESHADOWMAPVSDCT\n"
2410 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2412 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2416 "# ifdef USESHADOWSAMPLER\n"
2417 "# ifdef USESHADOWMAPPCF\n"
2418 "# define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r \n"
2419 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2420 " 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"
2422 " f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2425 "# ifdef USESHADOWMAPPCF\n"
2426 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2427 "# ifdef GL_ARB_texture_gather\n"
2428 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2430 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2432 " float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2433 "# if USESHADOWMAPPCF > 1\n"
2434 " float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2435 " float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2436 " float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2437 " float4 group4 = step(shadowmaptc.z, texval(-2.0, 0.0));\n"
2438 " float4 group5 = step(shadowmaptc.z, texval( 0.0, 0.0));\n"
2439 " float4 group6 = step(shadowmaptc.z, texval( 2.0, 0.0));\n"
2440 " float4 group7 = step(shadowmaptc.z, texval(-2.0, 2.0));\n"
2441 " float4 group8 = step(shadowmaptc.z, texval( 0.0, 2.0));\n"
2442 " float4 group9 = step(shadowmaptc.z, texval( 2.0, 2.0));\n"
2443 " float4 locols = float4(group1.ab, group3.ab);\n"
2444 " float4 hicols = float4(group7.rg, group9.rg);\n"
2445 " locols.yz += group2.ab;\n"
2446 " hicols.yz += group8.rg;\n"
2447 " float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2448 " float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2449 " lerp(locols, hicols, offset.y);\n"
2450 " float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2451 " cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2452 " f = dot(cols, float4(1.0/25.0));\n"
2454 " float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2455 " float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2456 " float4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
2457 " float4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
2458 " float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2459 " lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2460 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2463 "# ifdef GL_EXT_gpu_shader4\n"
2464 "# define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2466 "# define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r \n"
2468 "# if USESHADOWMAPPCF > 1\n"
2469 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2470 " center *= ShadowMap_TextureScale;\n"
2471 " 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"
2472 " 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"
2473 " 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"
2474 " 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"
2475 " float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2476 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2478 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2479 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2480 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2481 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2482 " float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2483 " f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2487 " f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2490 "# ifdef USESHADOWMAPORTHO\n"
2491 " return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2497 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2498 "#endif // FRAGMENT_SHADER\n"
2503 "#ifdef MODE_DEFERREDGEOMETRY\n"
2504 "#ifdef VERTEX_SHADER\n"
2507 "float4 gl_Vertex : POSITION,\n"
2508 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2509 "#ifdef USEVERTEXTEXTUREBLEND\n"
2510 "float4 gl_Color : COLOR0,\n"
2512 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2513 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2514 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2515 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2516 "uniform float4x4 TexMatrix : register(c0),\n"
2517 "#ifdef USEVERTEXTEXTUREBLEND\n"
2518 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2520 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2521 "#ifdef USEOFFSETMAPPING\n"
2522 "uniform float3 EyePosition : register(c24),\n"
2524 "out float4 gl_Position : POSITION,\n"
2525 "#ifdef USEVERTEXTEXTUREBLEND\n"
2526 "out float4 gl_FrontColor : COLOR,\n"
2528 "out float4 TexCoordBoth : TEXCOORD0,\n"
2529 "#ifdef USEOFFSETMAPPING\n"
2530 "out float3 EyeVector : TEXCOORD2,\n"
2532 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2533 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2534 "out float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\n"
2537 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2538 "#ifdef USEVERTEXTEXTUREBLEND\n"
2540 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2542 " gl_FrontColor = gl_Color; // Cg is forward\n"
2544 " TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2547 " // transform unnormalized eye direction into tangent space\n"
2548 "#ifdef USEOFFSETMAPPING\n"
2549 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2550 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2551 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2552 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2555 " VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2556 " VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2557 " VectorR.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2558 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2559 " VectorR.w = gl_Position.z;\n"
2561 "#endif // VERTEX_SHADER\n"
2563 "#ifdef FRAGMENT_SHADER\n"
2566 "float4 TexCoordBoth : TEXCOORD0,\n"
2567 "float3 EyeVector : TEXCOORD2,\n"
2568 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2569 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2570 "float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
2571 "uniform sampler Texture_Normal : register(s0),\n"
2572 "#ifdef USEALPHAKILL\n"
2573 "uniform sampler Texture_Color : register(s1),\n"
2575 "uniform sampler Texture_Gloss : register(s2),\n"
2576 "#ifdef USEVERTEXTEXTUREBLEND\n"
2577 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2578 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2580 "#ifdef USEOFFSETMAPPING\n"
2581 "uniform float OffsetMapping_Scale : register(c24),\n"
2583 "uniform half SpecularPower : register(c36),\n"
2585 "out float4 gl_FragData0 : COLOR0,\n"
2586 "out float4 gl_FragData1 : COLOR1\n"
2588 "out float4 gl_FragColor : COLOR\n"
2592 " float2 TexCoord = TexCoordBoth.xy;\n"
2593 "#ifdef USEOFFSETMAPPING\n"
2594 " // apply offsetmapping\n"
2595 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2596 "#define TexCoord TexCoordOffset\n"
2599 "#ifdef USEALPHAKILL\n"
2600 " if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2604 "#ifdef USEVERTEXTEXTUREBLEND\n"
2605 " float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2606 " float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2607 " //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2608 " //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2611 "#ifdef USEVERTEXTEXTUREBLEND\n"
2612 " float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2613 " float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2615 " float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2616 " float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2620 " 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"
2621 " float Depth = VectorR.w / 256.0;\n"
2622 " float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
2623 "// float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
2624 " depthcolor.yz -= floor(depthcolor.yz);\n"
2625 " gl_FragData1 = depthcolor;\n"
2627 " gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2630 "#endif // FRAGMENT_SHADER\n"
2631 "#else // !MODE_DEFERREDGEOMETRY\n"
2636 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2637 "#ifdef VERTEX_SHADER\n"
2640 "float4 gl_Vertex : POSITION,\n"
2641 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2642 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2643 "out float4 gl_Position : POSITION,\n"
2644 "out float4 ModelViewPosition : TEXCOORD0\n"
2647 " ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2648 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2650 "#endif // VERTEX_SHADER\n"
2652 "#ifdef FRAGMENT_SHADER\n"
2656 "float2 Pixel : VPOS,\n"
2658 "float2 Pixel : WPOS,\n"
2660 "float4 ModelViewPosition : TEXCOORD0,\n"
2661 "uniform float4x4 ViewToLight : register(c44),\n"
2662 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2663 "uniform float3 LightPosition : register(c23),\n"
2664 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2665 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2666 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2667 "#ifdef USESPECULAR\n"
2668 "uniform half3 DeferredColor_Specular : register(c11),\n"
2669 "uniform half SpecularPower : register(c36),\n"
2671 "uniform sampler Texture_Attenuation : register(s9),\n"
2672 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2673 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2675 "#ifdef USECUBEFILTER\n"
2676 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2679 "#ifdef USESHADOWMAP2D\n"
2680 "# ifdef USESHADOWSAMPLER\n"
2681 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2683 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2687 "#ifdef USESHADOWMAPVSDCT\n"
2688 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2691 "#if defined(USESHADOWMAP2D)\n"
2692 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2693 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2696 "out float4 gl_FragData0 : COLOR0,\n"
2697 "out float4 gl_FragData1 : COLOR1\n"
2700 " // calculate viewspace pixel position\n"
2701 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2702 " //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2703 " float3 position;\n"
2705 " position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
2707 " position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2709 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2710 " // decode viewspace pixel normal\n"
2711 " half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2712 " half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2713 " // surfacenormal = pixel normal in viewspace\n"
2714 " // LightVector = pixel to light in viewspace\n"
2715 " // CubeVector = position in lightspace\n"
2716 " // eyevector = pixel to view in viewspace\n"
2717 " float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2718 " half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2719 "#ifdef USEDIFFUSE\n"
2720 " // calculate diffuse shading\n"
2721 " half3 lightnormal = half3(normalize(LightPosition - position));\n"
2722 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2724 "#ifdef USESPECULAR\n"
2725 " // calculate directional shading\n"
2726 " float3 eyevector = position * -1.0;\n"
2727 "# ifdef USEEXACTSPECULARMATH\n"
2728 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
2730 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2731 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
2735 "#if defined(USESHADOWMAP2D)\n"
2736 " fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2737 "#ifdef USESHADOWMAPVSDCT\n"
2738 ", Texture_CubeProjection\n"
2743 "#ifdef USEDIFFUSE\n"
2744 " gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2746 " gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2748 "#ifdef USESPECULAR\n"
2749 " gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2751 " gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2754 "# ifdef USECUBEFILTER\n"
2755 " float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2756 " gl_FragData0.rgb *= cubecolor;\n"
2757 " gl_FragData1.rgb *= cubecolor;\n"
2760 "#endif // FRAGMENT_SHADER\n"
2761 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2766 "#ifdef VERTEX_SHADER\n"
2769 "float4 gl_Vertex : POSITION,\n"
2770 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2771 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2772 "float4 gl_Color : COLOR0,\n"
2774 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2775 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2776 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2777 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2778 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2780 "uniform float3 EyePosition : register(c24),\n"
2781 "uniform float4x4 TexMatrix : register(c0),\n"
2782 "#ifdef USEVERTEXTEXTUREBLEND\n"
2783 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2785 "#ifdef MODE_LIGHTSOURCE\n"
2786 "uniform float4x4 ModelToLight : register(c20),\n"
2788 "#ifdef MODE_LIGHTSOURCE\n"
2789 "uniform float3 LightPosition : register(c27),\n"
2791 "#ifdef MODE_LIGHTDIRECTION\n"
2792 "uniform float3 LightDir : register(c26),\n"
2794 "uniform float4 FogPlane : register(c25),\n"
2795 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2796 "uniform float3 LightPosition : register(c27),\n"
2798 "#ifdef USESHADOWMAPORTHO\n"
2799 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2801 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2802 "out float4 gl_FrontColor : COLOR,\n"
2804 "out float4 TexCoordBoth : TEXCOORD0,\n"
2805 "#ifdef USELIGHTMAP\n"
2806 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2808 "#ifdef USEEYEVECTOR\n"
2809 "out float3 EyeVector : TEXCOORD2,\n"
2811 "#ifdef USEREFLECTION\n"
2812 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2815 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2817 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE) || defined(USEDIFFUSE)\n"
2818 "out float3 LightVector : TEXCOORD1,\n"
2820 "#ifdef MODE_LIGHTSOURCE\n"
2821 "out float3 CubeVector : TEXCOORD3,\n"
2823 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2824 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2825 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2826 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2828 "#ifdef USESHADOWMAPORTHO\n"
2829 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2831 "out float4 gl_Position : POSITION\n"
2834 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2836 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2838 " gl_FrontColor = gl_Color; // Cg is forward\n"
2841 " // copy the surface texcoord\n"
2842 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2843 "#ifdef USEVERTEXTEXTUREBLEND\n"
2844 " TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2846 "#ifdef USELIGHTMAP\n"
2847 " TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2850 "#ifdef MODE_LIGHTSOURCE\n"
2851 " // transform vertex position into light attenuation/cubemap space\n"
2852 " // (-1 to +1 across the light box)\n"
2853 " CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2855 "# ifdef USEDIFFUSE\n"
2856 " // transform unnormalized light direction into tangent space\n"
2857 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
2858 " // normalize it per pixel)\n"
2859 " float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2860 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2861 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2862 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2866 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2867 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2868 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2869 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2872 " // transform unnormalized eye direction into tangent space\n"
2873 "#ifdef USEEYEVECTOR\n"
2874 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2875 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2876 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2877 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2881 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2882 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2885 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2886 " VectorS = gl_MultiTexCoord1.xyz;\n"
2887 " VectorT = gl_MultiTexCoord2.xyz;\n"
2888 " VectorR = gl_MultiTexCoord3.xyz;\n"
2891 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2892 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2894 "#ifdef USESHADOWMAPORTHO\n"
2895 " ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2898 "#ifdef USEREFLECTION\n"
2899 " ModelViewProjectionPosition = gl_Position;\n"
2902 "#endif // VERTEX_SHADER\n"
2907 "#ifdef FRAGMENT_SHADER\n"
2910 "#ifdef USEDEFERREDLIGHTMAP\n"
2912 "float2 Pixel : VPOS,\n"
2914 "float2 Pixel : WPOS,\n"
2917 "float4 gl_FrontColor : COLOR,\n"
2918 "float4 TexCoordBoth : TEXCOORD0,\n"
2919 "#ifdef USELIGHTMAP\n"
2920 "float2 TexCoordLightmap : TEXCOORD1,\n"
2922 "#ifdef USEEYEVECTOR\n"
2923 "float3 EyeVector : TEXCOORD2,\n"
2925 "#ifdef USEREFLECTION\n"
2926 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2929 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2931 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2932 "float3 LightVector : TEXCOORD1,\n"
2934 "#ifdef MODE_LIGHTSOURCE\n"
2935 "float3 CubeVector : TEXCOORD3,\n"
2937 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2938 "float4 ModelViewPosition : TEXCOORD0,\n"
2940 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2941 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2942 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2943 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2945 "#ifdef USESHADOWMAPORTHO\n"
2946 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2949 "uniform sampler Texture_Normal : register(s0),\n"
2950 "uniform sampler Texture_Color : register(s1),\n"
2951 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2952 "uniform sampler Texture_Gloss : register(s2),\n"
2955 "uniform sampler Texture_Glow : register(s3),\n"
2957 "#ifdef USEVERTEXTEXTUREBLEND\n"
2958 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2959 "uniform sampler Texture_SecondaryColor : register(s5),\n"
2960 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2961 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2964 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
2967 "#ifdef USECOLORMAPPING\n"
2968 "uniform sampler Texture_Pants : register(s4),\n"
2969 "uniform sampler Texture_Shirt : register(s7),\n"
2972 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
2973 "uniform sampler Texture_FogMask : register(s8),\n"
2975 "#ifdef USELIGHTMAP\n"
2976 "uniform sampler Texture_Lightmap : register(s9),\n"
2978 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2979 "uniform sampler Texture_Deluxemap : register(s10),\n"
2981 "#ifdef USEREFLECTION\n"
2982 "uniform sampler Texture_Reflection : register(s7),\n"
2985 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2986 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2987 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2989 "#ifdef USEDEFERREDLIGHTMAP\n"
2990 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2991 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2992 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
2993 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
2996 "#ifdef USECOLORMAPPING\n"
2997 "uniform half3 Color_Pants : register(c7),\n"
2998 "uniform half3 Color_Shirt : register(c8),\n"
3001 "uniform float3 FogColor : register(c16),\n"
3002 "uniform float FogRangeRecip : register(c20),\n"
3003 "uniform float FogPlaneViewDist : register(c19),\n"
3004 "uniform float FogHeightFade : register(c17),\n"
3007 "#ifdef USEOFFSETMAPPING\n"
3008 "uniform float OffsetMapping_Scale : register(c24),\n"
3011 "#ifdef USEDEFERREDLIGHTMAP\n"
3012 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
3013 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
3014 "uniform half3 DeferredMod_Specular : register(c13),\n"
3016 "uniform half3 Color_Ambient : register(c3),\n"
3017 "uniform half3 Color_Diffuse : register(c4),\n"
3018 "uniform half3 Color_Specular : register(c5),\n"
3019 "uniform half SpecularPower : register(c36),\n"
3021 "uniform half3 Color_Glow : register(c6),\n"
3023 "uniform half Alpha : register(c0),\n"
3024 "#ifdef USEREFLECTION\n"
3025 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3026 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3027 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3028 "uniform half4 ReflectColor : register(c26),\n"
3030 "#ifdef USEREFLECTCUBE\n"
3031 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3032 "uniform sampler Texture_ReflectMask : register(s5),\n"
3033 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3035 "#ifdef MODE_LIGHTDIRECTION\n"
3036 "uniform half3 LightColor : register(c21),\n"
3038 "#ifdef MODE_LIGHTSOURCE\n"
3039 "uniform half3 LightColor : register(c21),\n"
3042 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3043 "uniform sampler Texture_Attenuation : register(s9),\n"
3044 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3047 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3049 "#ifdef USESHADOWMAP2D\n"
3050 "# ifdef USESHADOWSAMPLER\n"
3051 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3053 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3057 "#ifdef USESHADOWMAPVSDCT\n"
3058 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3061 "#if defined(USESHADOWMAP2D)\n"
3062 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3063 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3065 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3067 "out float4 gl_FragColor : COLOR\n"
3070 " float2 TexCoord = TexCoordBoth.xy;\n"
3071 "#ifdef USEVERTEXTEXTUREBLEND\n"
3072 " float2 TexCoord2 = TexCoordBoth.zw;\n"
3074 "#ifdef USEOFFSETMAPPING\n"
3075 " // apply offsetmapping\n"
3076 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3077 "#define TexCoord TexCoordOffset\n"
3080 " // combine the diffuse textures (base, pants, shirt)\n"
3081 " half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3082 "#ifdef USEALPHAKILL\n"
3083 " if (color.a < 0.5)\n"
3086 " color.a *= Alpha;\n"
3087 "#ifdef USECOLORMAPPING\n"
3088 " color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3090 "#ifdef USEVERTEXTEXTUREBLEND\n"
3091 " half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3092 " //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3093 " //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3094 " color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3096 " //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3099 " // get the surface normal\n"
3100 "#ifdef USEVERTEXTEXTUREBLEND\n"
3101 " half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3103 " half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3106 " // get the material colors\n"
3107 " half3 diffusetex = color.rgb;\n"
3108 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3109 "# ifdef USEVERTEXTEXTUREBLEND\n"
3110 " half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3112 " half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3116 "#ifdef USEREFLECTCUBE\n"
3117 " float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3118 " float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3119 " float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3120 " diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3126 "#ifdef MODE_LIGHTSOURCE\n"
3127 " // light source\n"
3128 "#ifdef USEDIFFUSE\n"
3129 " half3 lightnormal = half3(normalize(LightVector));\n"
3130 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3131 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3132 "#ifdef USESPECULAR\n"
3133 "#ifdef USEEXACTSPECULARMATH\n"
3134 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3136 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3137 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3139 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3142 " color.rgb = diffusetex * Color_Ambient;\n"
3144 " color.rgb *= LightColor;\n"
3145 " color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3146 "#if defined(USESHADOWMAP2D)\n"
3147 " color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3148 "#ifdef USESHADOWMAPVSDCT\n"
3149 ", Texture_CubeProjection\n"
3154 "# ifdef USECUBEFILTER\n"
3155 " color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3158 "#ifdef USESHADOWMAP2D\n"
3159 "#ifdef USESHADOWMAPVSDCT\n"
3160 "// float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3162 "// float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3164 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3165 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3166 "// color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3167 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3168 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3169 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3170 "// color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3171 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3172 "// color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3173 "// color.r = half(shadowmaptc.z);\n"
3174 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3175 "// color.r = half(shadowmaptc.z);\n"
3177 "// color.rgb = abs(CubeVector);\n"
3179 "// color.rgb = half3(1,1,1);\n"
3180 "#endif // MODE_LIGHTSOURCE\n"
3185 "#ifdef MODE_LIGHTDIRECTION\n"
3187 "#ifdef USEDIFFUSE\n"
3188 " half3 lightnormal = half3(normalize(LightVector));\n"
3190 "#define lightcolor LightColor\n"
3191 "#endif // MODE_LIGHTDIRECTION\n"
3192 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3194 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3195 " half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3196 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3197 " // convert modelspace light vector to tangentspace\n"
3198 " half3 lightnormal;\n"
3199 " lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3200 " lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3201 " lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3202 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3203 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3204 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3205 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3206 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3207 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3208 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3209 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3210 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3211 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3212 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3213 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3215 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3216 " half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3217 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3223 "#ifdef MODE_FAKELIGHT\n"
3225 "half3 lightnormal = half3(normalize(EyeVector));\n"
3226 "half3 lightcolor = half3(1.0,1.0,1.0);\n"
3227 "#endif // MODE_FAKELIGHT\n"
3232 "#ifdef MODE_LIGHTMAP\n"
3233 " color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3234 "#endif // MODE_LIGHTMAP\n"
3235 "#ifdef MODE_VERTEXCOLOR\n"
3236 " color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3237 "#endif // MODE_VERTEXCOLOR\n"
3238 "#ifdef MODE_FLATCOLOR\n"
3239 " color.rgb = diffusetex * Color_Ambient;\n"
3240 "#endif // MODE_FLATCOLOR\n"
3246 "# ifdef USEDIFFUSE\n"
3247 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3248 "# ifdef USESPECULAR\n"
3249 "# ifdef USEEXACTSPECULARMATH\n"
3250 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3252 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3253 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3255 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3257 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3260 " color.rgb = diffusetex * Color_Ambient;\n"
3264 "#ifdef USESHADOWMAPORTHO\n"
3265 " color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
3268 "#ifdef USEDEFERREDLIGHTMAP\n"
3269 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3270 " color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3271 " color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3272 "// color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
3273 "// color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
3277 "#ifdef USEVERTEXTEXTUREBLEND\n"
3278 " color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3280 " color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3285 " color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3288 " // 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"
3289 "#ifdef USEREFLECTION\n"
3290 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3291 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3292 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3293 " float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3294 " // FIXME temporary hack to detect the case that the reflection\n"
3295 " // gets blackened at edges due to leaving the area that contains actual\n"
3297 " // Remove this 'ack once we have a better way to stop this thing from\n"
3299 " float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3300 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3301 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3302 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3303 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3304 " color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3307 " gl_FragColor = float4(color);\n"
3309 "#endif // FRAGMENT_SHADER\n"
3311 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3312 "#endif // !MODE_DEFERREDGEOMETRY\n"
3313 "#endif // !MODE_WATER\n"
3314 "#endif // !MODE_REFRACTION\n"
3315 "#endif // !MODE_BLOOMBLUR\n"
3316 "#endif // !MODE_GENERIC\n"
3317 "#endif // !MODE_POSTPROCESS\n"
3318 "#endif // !MODE_SHOWDEPTH\n"
3319 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3322 char *glslshaderstring = NULL;
3323 char *cgshaderstring = NULL;
3324 char *hlslshaderstring = NULL;
3326 //=======================================================================================================================================================
3328 typedef struct shaderpermutationinfo_s
3330 const char *pretext;
3333 shaderpermutationinfo_t;
3335 typedef struct shadermodeinfo_s
3337 const char *vertexfilename;
3338 const char *geometryfilename;
3339 const char *fragmentfilename;
3340 const char *pretext;
3345 typedef enum shaderpermutation_e
3347 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3348 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3349 SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only), use vertex colors (generic only)
3350 SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3351 SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3352 SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3353 SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3354 SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3355 SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3356 SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3357 SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3358 SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3359 SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3360 SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3361 SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3362 SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3363 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3364 SHADERPERMUTATION_SHADOWMAP2D = 1<<17, ///< (lightsource) use shadowmap texture as light filter
3365 SHADERPERMUTATION_SHADOWMAPPCF = 1<<18, ///< (lightsource) use percentage closer filtering on shadowmap test results
3366 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<19, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3367 SHADERPERMUTATION_SHADOWSAMPLER = 1<<20, ///< (lightsource) use hardware shadowmap test
3368 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<21, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3369 SHADERPERMUTATION_SHADOWMAPORTHO = 1<<22, //< (lightsource) use orthographic shadowmap projection
3370 SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<23, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3371 SHADERPERMUTATION_ALPHAKILL = 1<<24, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3372 SHADERPERMUTATION_REFLECTCUBE = 1<<25, ///< fake reflections using global cubemap (not HDRI light probe)
3373 SHADERPERMUTATION_NORMALMAPSCROLLBLEND = 1<<26, // (water) counter-direction normalmaps scrolling
3374 SHADERPERMUTATION_LIMIT = 1<<27, ///< size of permutations array
3375 SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
3377 shaderpermutation_t;
3379 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3380 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3382 {"#define USEDIFFUSE\n", " diffuse"},
3383 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3384 {"#define USEVIEWTINT\n", " viewtint"},
3385 {"#define USECOLORMAPPING\n", " colormapping"},
3386 {"#define USESATURATION\n", " saturation"},
3387 {"#define USEFOGINSIDE\n", " foginside"},
3388 {"#define USEFOGOUTSIDE\n", " fogoutside"},
3389 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3390 {"#define USEGAMMARAMPS\n", " gammaramps"},
3391 {"#define USECUBEFILTER\n", " cubefilter"},
3392 {"#define USEGLOW\n", " glow"},
3393 {"#define USEBLOOM\n", " bloom"},
3394 {"#define USESPECULAR\n", " specular"},
3395 {"#define USEPOSTPROCESSING\n", " postprocessing"},
3396 {"#define USEREFLECTION\n", " reflection"},
3397 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3398 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3399 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3400 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3401 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3402 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3403 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3404 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3405 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3406 {"#define USEALPHAKILL\n", " alphakill"},
3407 {"#define USEREFLECTCUBE\n", " reflectcube"},
3408 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
3411 // this enum selects which of the glslshadermodeinfo entries should be used
3412 typedef enum shadermode_e
3414 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3415 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3416 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3417 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3418 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3419 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3420 SHADERMODE_FAKELIGHT, ///< (fakelight) modulate texture by "fake" lighting (no lightmaps, no nothing)
3421 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3422 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3423 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3424 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3425 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3426 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3427 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3428 SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3429 SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3434 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3435 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3437 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3438 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3439 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3440 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3441 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3442 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3443 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3444 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3445 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3446 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3447 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3448 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3449 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3450 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3451 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3452 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3456 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3458 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3459 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3460 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3461 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3462 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3463 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3464 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FAKELIGHT\n", " fakelight"},
3465 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3466 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3467 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3468 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3469 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3470 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3471 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3472 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3473 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3478 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3480 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3481 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3482 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3483 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3484 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3485 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3486 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3487 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3488 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3489 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3490 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3491 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3492 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3493 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3494 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3495 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3499 struct r_glsl_permutation_s;
3500 typedef struct r_glsl_permutation_s
3502 /// hash lookup data
3503 struct r_glsl_permutation_s *hashnext;
3505 unsigned int permutation;
3507 /// indicates if we have tried compiling this permutation already
3509 /// 0 if compilation failed
3511 /// locations of detected uniforms in program object, or -1 if not found
3512 int loc_Texture_First;
3513 int loc_Texture_Second;
3514 int loc_Texture_GammaRamps;
3515 int loc_Texture_Normal;
3516 int loc_Texture_Color;
3517 int loc_Texture_Gloss;
3518 int loc_Texture_Glow;
3519 int loc_Texture_SecondaryNormal;
3520 int loc_Texture_SecondaryColor;
3521 int loc_Texture_SecondaryGloss;
3522 int loc_Texture_SecondaryGlow;
3523 int loc_Texture_Pants;
3524 int loc_Texture_Shirt;
3525 int loc_Texture_FogHeightTexture;
3526 int loc_Texture_FogMask;
3527 int loc_Texture_Lightmap;
3528 int loc_Texture_Deluxemap;
3529 int loc_Texture_Attenuation;
3530 int loc_Texture_Cube;
3531 int loc_Texture_Refraction;
3532 int loc_Texture_Reflection;
3533 int loc_Texture_ShadowMap2D;
3534 int loc_Texture_CubeProjection;
3535 int loc_Texture_ScreenDepth;
3536 int loc_Texture_ScreenNormalMap;
3537 int loc_Texture_ScreenDiffuse;
3538 int loc_Texture_ScreenSpecular;
3539 int loc_Texture_ReflectMask;
3540 int loc_Texture_ReflectCube;
3542 int loc_BloomBlur_Parameters;
3544 int loc_Color_Ambient;
3545 int loc_Color_Diffuse;
3546 int loc_Color_Specular;
3548 int loc_Color_Pants;
3549 int loc_Color_Shirt;
3550 int loc_DeferredColor_Ambient;
3551 int loc_DeferredColor_Diffuse;
3552 int loc_DeferredColor_Specular;
3553 int loc_DeferredMod_Diffuse;
3554 int loc_DeferredMod_Specular;
3555 int loc_DistortScaleRefractReflect;
3556 int loc_EyePosition;
3558 int loc_FogHeightFade;
3560 int loc_FogPlaneViewDist;
3561 int loc_FogRangeRecip;
3564 int loc_LightPosition;
3565 int loc_OffsetMapping_Scale;
3567 int loc_ReflectColor;
3568 int loc_ReflectFactor;
3569 int loc_ReflectOffset;
3570 int loc_RefractColor;
3572 int loc_ScreenCenterRefractReflect;
3573 int loc_ScreenScaleRefractReflect;
3574 int loc_ScreenToDepth;
3575 int loc_ShadowMap_Parameters;
3576 int loc_ShadowMap_TextureScale;
3577 int loc_SpecularPower;
3582 int loc_ViewTintColor;
3583 int loc_ViewToLight;
3584 int loc_ModelToLight;
3586 int loc_BackgroundTexMatrix;
3587 int loc_ModelViewProjectionMatrix;
3588 int loc_ModelViewMatrix;
3589 int loc_PixelToScreenTexCoord;
3590 int loc_ModelToReflectCube;
3591 int loc_ShadowMapMatrix;
3592 int loc_BloomColorSubtract;
3593 int loc_NormalmapScrollBlend;
3595 r_glsl_permutation_t;
3597 #define SHADERPERMUTATION_HASHSIZE 256
3600 // non-degradable "lightweight" shader parameters to keep the permutations simpler
3601 // these can NOT degrade! only use for simple stuff
3604 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
3605 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3606 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
3607 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
3608 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
3609 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5 ///< postprocess uservec4 is enabled
3611 #define SHADERSTATICPARMS_COUNT 6
3613 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
3614 static int shaderstaticparms_count = 0;
3616 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
3617 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
3618 qboolean R_CompileShader_CheckStaticParms(void)
3620 static int r_compileshader_staticparms_save[1];
3621 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
3622 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
3625 if (r_glsl_saturation_redcompensate.integer)
3626 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
3627 if (r_shadow_glossexact.integer)
3628 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
3629 if (r_glsl_postprocess.integer)
3631 if (r_glsl_postprocess_uservec1_enable.integer)
3632 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
3633 if (r_glsl_postprocess_uservec2_enable.integer)
3634 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
3635 if (r_glsl_postprocess_uservec3_enable.integer)
3636 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
3637 if (r_glsl_postprocess_uservec4_enable.integer)
3638 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
3640 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
3643 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
3644 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
3645 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
3647 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
3648 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
3650 shaderstaticparms_count = 0;
3653 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
3654 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
3655 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
3656 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
3657 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
3658 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
3661 /// information about each possible shader permutation
3662 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3663 /// currently selected permutation
3664 r_glsl_permutation_t *r_glsl_permutation;
3665 /// storage for permutations linked in the hash table
3666 memexpandablearray_t r_glsl_permutationarray;
3668 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3670 //unsigned int hashdepth = 0;
3671 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3672 r_glsl_permutation_t *p;
3673 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3675 if (p->mode == mode && p->permutation == permutation)
3677 //if (hashdepth > 10)
3678 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3683 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3685 p->permutation = permutation;
3686 p->hashnext = r_glsl_permutationhash[mode][hashindex];
3687 r_glsl_permutationhash[mode][hashindex] = p;
3688 //if (hashdepth > 10)
3689 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3693 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3696 if (!filename || !filename[0])
3698 if (!strcmp(filename, "glsl/default.glsl"))
3700 if (!glslshaderstring)
3702 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3703 if (glslshaderstring)
3704 Con_DPrintf("Loading shaders from file %s...\n", filename);
3706 glslshaderstring = (char *)builtinshaderstring;
3708 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3709 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3710 return shaderstring;
3712 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3715 if (printfromdisknotice)
3716 Con_DPrintf("from disk %s... ", filename);
3717 return shaderstring;
3719 return shaderstring;
3722 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3725 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3726 char *vertexstring, *geometrystring, *fragmentstring;
3727 char permutationname[256];
3728 int vertstrings_count = 0;
3729 int geomstrings_count = 0;
3730 int fragstrings_count = 0;
3731 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3732 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3733 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3740 permutationname[0] = 0;
3741 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
3742 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3743 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3745 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3747 // the first pretext is which type of shader to compile as
3748 // (later these will all be bound together as a program object)
3749 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3750 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3751 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3753 // the second pretext is the mode (for example a light source)
3754 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3755 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3756 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3757 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3759 // now add all the permutation pretexts
3760 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3762 if (permutation & (1<<i))
3764 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3765 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3766 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3767 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3771 // keep line numbers correct
3772 vertstrings_list[vertstrings_count++] = "\n";
3773 geomstrings_list[geomstrings_count++] = "\n";
3774 fragstrings_list[fragstrings_count++] = "\n";
3779 R_CompileShader_AddStaticParms(mode, permutation);
3780 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3781 vertstrings_count += shaderstaticparms_count;
3782 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3783 geomstrings_count += shaderstaticparms_count;
3784 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3785 fragstrings_count += shaderstaticparms_count;
3787 // now append the shader text itself
3788 vertstrings_list[vertstrings_count++] = vertexstring;
3789 geomstrings_list[geomstrings_count++] = geometrystring;
3790 fragstrings_list[fragstrings_count++] = fragmentstring;
3792 // if any sources were NULL, clear the respective list
3794 vertstrings_count = 0;
3795 if (!geometrystring)
3796 geomstrings_count = 0;
3797 if (!fragmentstring)
3798 fragstrings_count = 0;
3800 // compile the shader program
3801 if (vertstrings_count + geomstrings_count + fragstrings_count)
3802 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3806 qglUseProgramObjectARB(p->program);CHECKGLERROR
3807 // look up all the uniform variable names we care about, so we don't
3808 // have to look them up every time we set them
3810 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
3811 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
3812 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3813 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
3814 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
3815 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3816 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
3817 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3818 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3819 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3820 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3821 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
3822 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3823 p->loc_Texture_FogHeightTexture = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3824 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3825 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3826 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3827 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3828 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
3829 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3830 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3831 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3832 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3833 p->loc_Texture_ScreenDepth = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3834 p->loc_Texture_ScreenNormalMap = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3835 p->loc_Texture_ScreenDiffuse = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3836 p->loc_Texture_ScreenSpecular = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3837 p->loc_Texture_ReflectMask = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3838 p->loc_Texture_ReflectCube = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3839 p->loc_Alpha = qglGetUniformLocationARB(p->program, "Alpha");
3840 p->loc_BloomBlur_Parameters = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3841 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
3842 p->loc_Color_Ambient = qglGetUniformLocationARB(p->program, "Color_Ambient");
3843 p->loc_Color_Diffuse = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3844 p->loc_Color_Specular = qglGetUniformLocationARB(p->program, "Color_Specular");
3845 p->loc_Color_Glow = qglGetUniformLocationARB(p->program, "Color_Glow");
3846 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
3847 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
3848 p->loc_DeferredColor_Ambient = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3849 p->loc_DeferredColor_Diffuse = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3850 p->loc_DeferredColor_Specular = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3851 p->loc_DeferredMod_Diffuse = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3852 p->loc_DeferredMod_Specular = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3853 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3854 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
3855 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
3856 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
3857 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
3858 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3859 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3860 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
3861 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
3862 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
3863 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3864 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
3865 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
3866 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
3867 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
3868 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
3869 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
3870 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3871 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3872 p->loc_ScreenToDepth = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3873 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3874 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3875 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
3876 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
3877 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
3878 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
3879 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
3880 p->loc_ViewTintColor = qglGetUniformLocationARB(p->program, "ViewTintColor");
3881 p->loc_ViewToLight = qglGetUniformLocationARB(p->program, "ViewToLight");
3882 p->loc_ModelToLight = qglGetUniformLocationARB(p->program, "ModelToLight");
3883 p->loc_TexMatrix = qglGetUniformLocationARB(p->program, "TexMatrix");
3884 p->loc_BackgroundTexMatrix = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3885 p->loc_ModelViewMatrix = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3886 p->loc_ModelViewProjectionMatrix = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3887 p->loc_PixelToScreenTexCoord = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3888 p->loc_ModelToReflectCube = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3889 p->loc_ShadowMapMatrix = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3890 p->loc_BloomColorSubtract = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
3891 p->loc_NormalmapScrollBlend = qglGetUniformLocationARB(p->program, "NormalmapScrollBlend");
3892 // initialize the samplers to refer to the texture units we use
3893 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
3894 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
3895 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
3896 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
3897 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
3898 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
3899 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
3900 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3901 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3902 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3903 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
3904 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
3905 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
3906 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3907 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
3908 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
3909 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
3910 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
3911 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
3912 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
3913 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
3914 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
3915 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3916 if (p->loc_Texture_ScreenDepth >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth , GL20TU_SCREENDEPTH);
3917 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3918 if (p->loc_Texture_ScreenDiffuse >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse , GL20TU_SCREENDIFFUSE);
3919 if (p->loc_Texture_ScreenSpecular >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3920 if (p->loc_Texture_ReflectMask >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask , GL20TU_REFLECTMASK);
3921 if (p->loc_Texture_ReflectCube >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube , GL20TU_REFLECTCUBE);
3923 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3926 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
3930 Mem_Free(vertexstring);
3932 Mem_Free(geometrystring);
3934 Mem_Free(fragmentstring);
3937 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3939 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3940 if (r_glsl_permutation != perm)
3942 r_glsl_permutation = perm;
3943 if (!r_glsl_permutation->program)
3945 if (!r_glsl_permutation->compiled)
3946 R_GLSL_CompilePermutation(perm, mode, permutation);
3947 if (!r_glsl_permutation->program)
3949 // remove features until we find a valid permutation
3951 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3953 // reduce i more quickly whenever it would not remove any bits
3954 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3955 if (!(permutation & j))
3958 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3959 if (!r_glsl_permutation->compiled)
3960 R_GLSL_CompilePermutation(perm, mode, permutation);
3961 if (r_glsl_permutation->program)
3964 if (i >= SHADERPERMUTATION_COUNT)
3966 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3967 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3968 qglUseProgramObjectARB(0);CHECKGLERROR
3969 return; // no bit left to clear, entire mode is broken
3974 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3976 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3977 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3978 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3982 #include <Cg/cgGL.h>
3983 struct r_cg_permutation_s;
3984 typedef struct r_cg_permutation_s
3986 /// hash lookup data
3987 struct r_cg_permutation_s *hashnext;
3989 unsigned int permutation;
3991 /// indicates if we have tried compiling this permutation already
3993 /// 0 if compilation failed
3996 /// locations of detected parameters in programs, or NULL if not found
3997 CGparameter vp_EyePosition;
3998 CGparameter vp_FogPlane;
3999 CGparameter vp_LightDir;
4000 CGparameter vp_LightPosition;
4001 CGparameter vp_ModelToLight;
4002 CGparameter vp_TexMatrix;
4003 CGparameter vp_BackgroundTexMatrix;
4004 CGparameter vp_ModelViewProjectionMatrix;
4005 CGparameter vp_ModelViewMatrix;
4006 CGparameter vp_ShadowMapMatrix;
4008 CGparameter fp_Texture_First;
4009 CGparameter fp_Texture_Second;
4010 CGparameter fp_Texture_GammaRamps;
4011 CGparameter fp_Texture_Normal;
4012 CGparameter fp_Texture_Color;
4013 CGparameter fp_Texture_Gloss;
4014 CGparameter fp_Texture_Glow;
4015 CGparameter fp_Texture_SecondaryNormal;
4016 CGparameter fp_Texture_SecondaryColor;
4017 CGparameter fp_Texture_SecondaryGloss;
4018 CGparameter fp_Texture_SecondaryGlow;
4019 CGparameter fp_Texture_Pants;
4020 CGparameter fp_Texture_Shirt;
4021 CGparameter fp_Texture_FogHeightTexture;
4022 CGparameter fp_Texture_FogMask;
4023 CGparameter fp_Texture_Lightmap;
4024 CGparameter fp_Texture_Deluxemap;
4025 CGparameter fp_Texture_Attenuation;
4026 CGparameter fp_Texture_Cube;
4027 CGparameter fp_Texture_Refraction;
4028 CGparameter fp_Texture_Reflection;
4029 CGparameter fp_Texture_ShadowMap2D;
4030 CGparameter fp_Texture_CubeProjection;
4031 CGparameter fp_Texture_ScreenDepth;
4032 CGparameter fp_Texture_ScreenNormalMap;
4033 CGparameter fp_Texture_ScreenDiffuse;
4034 CGparameter fp_Texture_ScreenSpecular;
4035 CGparameter fp_Texture_ReflectMask;
4036 CGparameter fp_Texture_ReflectCube;
4037 CGparameter fp_Alpha;
4038 CGparameter fp_BloomBlur_Parameters;
4039 CGparameter fp_ClientTime;
4040 CGparameter fp_Color_Ambient;
4041 CGparameter fp_Color_Diffuse;
4042 CGparameter fp_Color_Specular;
4043 CGparameter fp_Color_Glow;
4044 CGparameter fp_Color_Pants;
4045 CGparameter fp_Color_Shirt;
4046 CGparameter fp_DeferredColor_Ambient;
4047 CGparameter fp_DeferredColor_Diffuse;
4048 CGparameter fp_DeferredColor_Specular;
4049 CGparameter fp_DeferredMod_Diffuse;
4050 CGparameter fp_DeferredMod_Specular;
4051 CGparameter fp_DistortScaleRefractReflect;
4052 CGparameter fp_EyePosition;
4053 CGparameter fp_FogColor;
4054 CGparameter fp_FogHeightFade;
4055 CGparameter fp_FogPlane;
4056 CGparameter fp_FogPlaneViewDist;
4057 CGparameter fp_FogRangeRecip;
4058 CGparameter fp_LightColor;
4059 CGparameter fp_LightDir;
4060 CGparameter fp_LightPosition;
4061 CGparameter fp_OffsetMapping_Scale;
4062 CGparameter fp_PixelSize;
4063 CGparameter fp_ReflectColor;
4064 CGparameter fp_ReflectFactor;
4065 CGparameter fp_ReflectOffset;
4066 CGparameter fp_RefractColor;
4067 CGparameter fp_Saturation;
4068 CGparameter fp_ScreenCenterRefractReflect;
4069 CGparameter fp_ScreenScaleRefractReflect;
4070 CGparameter fp_ScreenToDepth;
4071 CGparameter fp_ShadowMap_Parameters;
4072 CGparameter fp_ShadowMap_TextureScale;
4073 CGparameter fp_SpecularPower;
4074 CGparameter fp_UserVec1;
4075 CGparameter fp_UserVec2;
4076 CGparameter fp_UserVec3;
4077 CGparameter fp_UserVec4;
4078 CGparameter fp_ViewTintColor;
4079 CGparameter fp_ViewToLight;
4080 CGparameter fp_PixelToScreenTexCoord;
4081 CGparameter fp_ModelToReflectCube;
4082 CGparameter fp_BloomColorSubtract;
4083 CGparameter fp_NormalmapScrollBlend;
4087 /// information about each possible shader permutation
4088 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4089 /// currently selected permutation
4090 r_cg_permutation_t *r_cg_permutation;
4091 /// storage for permutations linked in the hash table
4092 memexpandablearray_t r_cg_permutationarray;
4094 #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));}}
4096 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
4098 //unsigned int hashdepth = 0;
4099 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4100 r_cg_permutation_t *p;
4101 for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4103 if (p->mode == mode && p->permutation == permutation)
4105 //if (hashdepth > 10)
4106 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4111 p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4113 p->permutation = permutation;
4114 p->hashnext = r_cg_permutationhash[mode][hashindex];
4115 r_cg_permutationhash[mode][hashindex] = p;
4116 //if (hashdepth > 10)
4117 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4121 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4124 if (!filename || !filename[0])
4126 if (!strcmp(filename, "cg/default.cg"))
4128 if (!cgshaderstring)
4130 cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4132 Con_DPrintf("Loading shaders from file %s...\n", filename);
4134 cgshaderstring = (char *)builtincgshaderstring;
4136 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4137 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4138 return shaderstring;
4140 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4143 if (printfromdisknotice)
4144 Con_DPrintf("from disk %s... ", filename);
4145 return shaderstring;
4147 return shaderstring;
4150 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4152 // TODO: load or create .fp and .vp shader files
4155 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4158 shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4159 int vertstring_length = 0;
4160 int geomstring_length = 0;
4161 int fragstring_length = 0;
4163 char *vertexstring, *geometrystring, *fragmentstring;
4164 char *vertstring, *geomstring, *fragstring;
4165 char permutationname[256];
4166 char cachename[256];
4167 CGprofile vertexProfile;
4168 CGprofile fragmentProfile;
4169 int vertstrings_count = 0;
4170 int geomstrings_count = 0;
4171 int fragstrings_count = 0;
4172 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4173 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4174 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4182 permutationname[0] = 0;
4184 vertexstring = R_CG_GetText(modeinfo->vertexfilename, true);
4185 geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4186 fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4188 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4189 strlcat(cachename, "cg/", sizeof(cachename));
4191 // the first pretext is which type of shader to compile as
4192 // (later these will all be bound together as a program object)
4193 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4194 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4195 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4197 // the second pretext is the mode (for example a light source)
4198 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4199 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4200 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4201 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4202 strlcat(cachename, modeinfo->name, sizeof(cachename));
4204 // now add all the permutation pretexts
4205 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4207 if (permutation & (1<<i))
4209 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4210 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4211 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4212 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4213 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4217 // keep line numbers correct
4218 vertstrings_list[vertstrings_count++] = "\n";
4219 geomstrings_list[geomstrings_count++] = "\n";
4220 fragstrings_list[fragstrings_count++] = "\n";
4225 R_CompileShader_AddStaticParms(mode, permutation);
4226 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4227 vertstrings_count += shaderstaticparms_count;
4228 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4229 geomstrings_count += shaderstaticparms_count;
4230 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4231 fragstrings_count += shaderstaticparms_count;
4233 // replace spaces in the cachename with _ characters
4234 for (i = 0;cachename[i];i++)
4235 if (cachename[i] == ' ')
4238 // now append the shader text itself
4239 vertstrings_list[vertstrings_count++] = vertexstring;
4240 geomstrings_list[geomstrings_count++] = geometrystring;
4241 fragstrings_list[fragstrings_count++] = fragmentstring;
4243 // if any sources were NULL, clear the respective list
4245 vertstrings_count = 0;
4246 if (!geometrystring)
4247 geomstrings_count = 0;
4248 if (!fragmentstring)
4249 fragstrings_count = 0;
4251 vertstring_length = 0;
4252 for (i = 0;i < vertstrings_count;i++)
4253 vertstring_length += strlen(vertstrings_list[i]);
4254 vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4255 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4256 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4258 geomstring_length = 0;
4259 for (i = 0;i < geomstrings_count;i++)
4260 geomstring_length += strlen(geomstrings_list[i]);
4261 geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4262 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4263 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4265 fragstring_length = 0;
4266 for (i = 0;i < fragstrings_count;i++)
4267 fragstring_length += strlen(fragstrings_list[i]);
4268 fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4269 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4270 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4274 //vertexProfile = CG_PROFILE_ARBVP1;
4275 //fragmentProfile = CG_PROFILE_ARBFP1;
4276 vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4277 fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4278 //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4279 //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4280 //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4283 // try to load the cached shader, or generate one
4284 R_CG_CacheShader(p, cachename, vertstring, fragstring);
4286 // if caching failed, do a dynamic compile for now
4288 if (vertstring[0] && !p->vprogram)
4289 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4291 if (fragstring[0] && !p->fprogram)
4292 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4295 // look up all the uniform variable names we care about, so we don't
4296 // have to look them up every time we set them
4300 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4301 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4302 p->vp_EyePosition = cgGetNamedParameter(p->vprogram, "EyePosition");
4303 p->vp_FogPlane = cgGetNamedParameter(p->vprogram, "FogPlane");
4304 p->vp_LightDir = cgGetNamedParameter(p->vprogram, "LightDir");
4305 p->vp_LightPosition = cgGetNamedParameter(p->vprogram, "LightPosition");
4306 p->vp_ModelToLight = cgGetNamedParameter(p->vprogram, "ModelToLight");
4307 p->vp_TexMatrix = cgGetNamedParameter(p->vprogram, "TexMatrix");
4308 p->vp_BackgroundTexMatrix = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4309 p->vp_ModelViewProjectionMatrix = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4310 p->vp_ModelViewMatrix = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4311 p->vp_ShadowMapMatrix = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4317 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4318 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4319 p->fp_Texture_First = cgGetNamedParameter(p->fprogram, "Texture_First");
4320 p->fp_Texture_Second = cgGetNamedParameter(p->fprogram, "Texture_Second");
4321 p->fp_Texture_GammaRamps = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4322 p->fp_Texture_Normal = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4323 p->fp_Texture_Color = cgGetNamedParameter(p->fprogram, "Texture_Color");
4324 p->fp_Texture_Gloss = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4325 p->fp_Texture_Glow = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4326 p->fp_Texture_SecondaryNormal = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4327 p->fp_Texture_SecondaryColor = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4328 p->fp_Texture_SecondaryGloss = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4329 p->fp_Texture_SecondaryGlow = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4330 p->fp_Texture_Pants = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4331 p->fp_Texture_Shirt = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4332 p->fp_Texture_FogHeightTexture = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4333 p->fp_Texture_FogMask = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4334 p->fp_Texture_Lightmap = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4335 p->fp_Texture_Deluxemap = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4336 p->fp_Texture_Attenuation = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4337 p->fp_Texture_Cube = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4338 p->fp_Texture_Refraction = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4339 p->fp_Texture_Reflection = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4340 p->fp_Texture_ShadowMap2D = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4341 p->fp_Texture_CubeProjection = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4342 p->fp_Texture_ScreenDepth = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4343 p->fp_Texture_ScreenNormalMap = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4344 p->fp_Texture_ScreenDiffuse = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4345 p->fp_Texture_ScreenSpecular = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4346 p->fp_Texture_ReflectMask = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4347 p->fp_Texture_ReflectCube = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4348 p->fp_Alpha = cgGetNamedParameter(p->fprogram, "Alpha");
4349 p->fp_BloomBlur_Parameters = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4350 p->fp_ClientTime = cgGetNamedParameter(p->fprogram, "ClientTime");
4351 p->fp_Color_Ambient = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4352 p->fp_Color_Diffuse = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4353 p->fp_Color_Specular = cgGetNamedParameter(p->fprogram, "Color_Specular");
4354 p->fp_Color_Glow = cgGetNamedParameter(p->fprogram, "Color_Glow");
4355 p->fp_Color_Pants = cgGetNamedParameter(p->fprogram, "Color_Pants");
4356 p->fp_Color_Shirt = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4357 p->fp_DeferredColor_Ambient = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4358 p->fp_DeferredColor_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4359 p->fp_DeferredColor_Specular = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4360 p->fp_DeferredMod_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4361 p->fp_DeferredMod_Specular = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4362 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4363 p->fp_EyePosition = cgGetNamedParameter(p->fprogram, "EyePosition");
4364 p->fp_FogColor = cgGetNamedParameter(p->fprogram, "FogColor");
4365 p->fp_FogHeightFade = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4366 p->fp_FogPlane = cgGetNamedParameter(p->fprogram, "FogPlane");
4367 p->fp_FogPlaneViewDist = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4368 p->fp_FogRangeRecip = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4369 p->fp_LightColor = cgGetNamedParameter(p->fprogram, "LightColor");
4370 p->fp_LightDir = cgGetNamedParameter(p->fprogram, "LightDir");
4371 p->fp_LightPosition = cgGetNamedParameter(p->fprogram, "LightPosition");
4372 p->fp_OffsetMapping_Scale = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4373 p->fp_PixelSize = cgGetNamedParameter(p->fprogram, "PixelSize");
4374 p->fp_ReflectColor = cgGetNamedParameter(p->fprogram, "ReflectColor");
4375 p->fp_ReflectFactor = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4376 p->fp_ReflectOffset = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4377 p->fp_RefractColor = cgGetNamedParameter(p->fprogram, "RefractColor");
4378 p->fp_Saturation = cgGetNamedParameter(p->fprogram, "Saturation");
4379 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4380 p->fp_ScreenScaleRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4381 p->fp_ScreenToDepth = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4382 p->fp_ShadowMap_Parameters = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4383 p->fp_ShadowMap_TextureScale = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4384 p->fp_SpecularPower = cgGetNamedParameter(p->fprogram, "SpecularPower");
4385 p->fp_UserVec1 = cgGetNamedParameter(p->fprogram, "UserVec1");
4386 p->fp_UserVec2 = cgGetNamedParameter(p->fprogram, "UserVec2");
4387 p->fp_UserVec3 = cgGetNamedParameter(p->fprogram, "UserVec3");
4388 p->fp_UserVec4 = cgGetNamedParameter(p->fprogram, "UserVec4");
4389 p->fp_ViewTintColor = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4390 p->fp_ViewToLight = cgGetNamedParameter(p->fprogram, "ViewToLight");
4391 p->fp_PixelToScreenTexCoord = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4392 p->fp_ModelToReflectCube = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4393 p->fp_BloomColorSubtract = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4394 p->fp_NormalmapScrollBlend = cgGetNamedParameter(p->fprogram, "NormalmapScrollBlend");
4398 if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4399 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4401 Con_Printf("^1CG shader %s failed! some features may not work properly.\n", permutationname);
4405 Mem_Free(vertstring);
4407 Mem_Free(geomstring);
4409 Mem_Free(fragstring);
4411 Mem_Free(vertexstring);
4413 Mem_Free(geometrystring);
4415 Mem_Free(fragmentstring);
4418 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4420 r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4423 if (r_cg_permutation != perm)
4425 r_cg_permutation = perm;
4426 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4428 if (!r_cg_permutation->compiled)
4429 R_CG_CompilePermutation(perm, mode, permutation);
4430 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4432 // remove features until we find a valid permutation
4434 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4436 // reduce i more quickly whenever it would not remove any bits
4437 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4438 if (!(permutation & j))
4441 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4442 if (!r_cg_permutation->compiled)
4443 R_CG_CompilePermutation(perm, mode, permutation);
4444 if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4447 if (i >= SHADERPERMUTATION_COUNT)
4449 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4450 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4451 return; // no bit left to clear, entire mode is broken
4457 if (r_cg_permutation->vprogram)
4459 cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4460 cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4461 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4465 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4466 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4468 if (r_cg_permutation->fprogram)
4470 cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4471 cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4472 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4476 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4477 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4481 if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4482 if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4483 if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4486 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4488 cgGLSetTextureParameter(param, R_GetTexture(tex));
4489 cgGLEnableTextureParameter(param);
4497 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4498 extern D3DCAPS9 vid_d3d9caps;
4501 struct r_hlsl_permutation_s;
4502 typedef struct r_hlsl_permutation_s
4504 /// hash lookup data
4505 struct r_hlsl_permutation_s *hashnext;
4507 unsigned int permutation;
4509 /// indicates if we have tried compiling this permutation already
4511 /// NULL if compilation failed
4512 IDirect3DVertexShader9 *vertexshader;
4513 IDirect3DPixelShader9 *pixelshader;
4515 r_hlsl_permutation_t;
4517 typedef enum D3DVSREGISTER_e
4519 D3DVSREGISTER_TexMatrix = 0, // float4x4
4520 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4521 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4522 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4523 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4524 D3DVSREGISTER_ModelToLight = 20, // float4x4
4525 D3DVSREGISTER_EyePosition = 24,
4526 D3DVSREGISTER_FogPlane = 25,
4527 D3DVSREGISTER_LightDir = 26,
4528 D3DVSREGISTER_LightPosition = 27,
4532 typedef enum D3DPSREGISTER_e
4534 D3DPSREGISTER_Alpha = 0,
4535 D3DPSREGISTER_BloomBlur_Parameters = 1,
4536 D3DPSREGISTER_ClientTime = 2,
4537 D3DPSREGISTER_Color_Ambient = 3,
4538 D3DPSREGISTER_Color_Diffuse = 4,
4539 D3DPSREGISTER_Color_Specular = 5,
4540 D3DPSREGISTER_Color_Glow = 6,
4541 D3DPSREGISTER_Color_Pants = 7,
4542 D3DPSREGISTER_Color_Shirt = 8,
4543 D3DPSREGISTER_DeferredColor_Ambient = 9,
4544 D3DPSREGISTER_DeferredColor_Diffuse = 10,
4545 D3DPSREGISTER_DeferredColor_Specular = 11,
4546 D3DPSREGISTER_DeferredMod_Diffuse = 12,
4547 D3DPSREGISTER_DeferredMod_Specular = 13,
4548 D3DPSREGISTER_DistortScaleRefractReflect = 14,
4549 D3DPSREGISTER_EyePosition = 15, // unused
4550 D3DPSREGISTER_FogColor = 16,
4551 D3DPSREGISTER_FogHeightFade = 17,
4552 D3DPSREGISTER_FogPlane = 18,
4553 D3DPSREGISTER_FogPlaneViewDist = 19,
4554 D3DPSREGISTER_FogRangeRecip = 20,
4555 D3DPSREGISTER_LightColor = 21,
4556 D3DPSREGISTER_LightDir = 22, // unused
4557 D3DPSREGISTER_LightPosition = 23,
4558 D3DPSREGISTER_OffsetMapping_Scale = 24,
4559 D3DPSREGISTER_PixelSize = 25,
4560 D3DPSREGISTER_ReflectColor = 26,
4561 D3DPSREGISTER_ReflectFactor = 27,
4562 D3DPSREGISTER_ReflectOffset = 28,
4563 D3DPSREGISTER_RefractColor = 29,
4564 D3DPSREGISTER_Saturation = 30,
4565 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4566 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4567 D3DPSREGISTER_ScreenToDepth = 33,
4568 D3DPSREGISTER_ShadowMap_Parameters = 34,
4569 D3DPSREGISTER_ShadowMap_TextureScale = 35,
4570 D3DPSREGISTER_SpecularPower = 36,
4571 D3DPSREGISTER_UserVec1 = 37,
4572 D3DPSREGISTER_UserVec2 = 38,
4573 D3DPSREGISTER_UserVec3 = 39,
4574 D3DPSREGISTER_UserVec4 = 40,
4575 D3DPSREGISTER_ViewTintColor = 41,
4576 D3DPSREGISTER_PixelToScreenTexCoord = 42,
4577 D3DPSREGISTER_BloomColorSubtract = 43,
4578 D3DPSREGISTER_ViewToLight = 44, // float4x4
4579 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4580 D3DPSREGISTER_NormalmapScrollBlend = 52,
4585 /// information about each possible shader permutation
4586 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4587 /// currently selected permutation
4588 r_hlsl_permutation_t *r_hlsl_permutation;
4589 /// storage for permutations linked in the hash table
4590 memexpandablearray_t r_hlsl_permutationarray;
4592 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4594 //unsigned int hashdepth = 0;
4595 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4596 r_hlsl_permutation_t *p;
4597 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4599 if (p->mode == mode && p->permutation == permutation)
4601 //if (hashdepth > 10)
4602 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4607 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4609 p->permutation = permutation;
4610 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4611 r_hlsl_permutationhash[mode][hashindex] = p;
4612 //if (hashdepth > 10)
4613 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4617 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4620 if (!filename || !filename[0])
4622 if (!strcmp(filename, "hlsl/default.hlsl"))
4624 if (!hlslshaderstring)
4626 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4627 if (hlslshaderstring)
4628 Con_DPrintf("Loading shaders from file %s...\n", filename);
4630 hlslshaderstring = (char *)builtincgshaderstring;
4632 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4633 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4634 return shaderstring;
4636 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4639 if (printfromdisknotice)
4640 Con_DPrintf("from disk %s... ", filename);
4641 return shaderstring;
4643 return shaderstring;
4647 //#include <d3dx9shader.h>
4648 //#include <d3dx9mesh.h>
4650 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4652 DWORD *vsbin = NULL;
4653 DWORD *psbin = NULL;
4654 fs_offset_t vsbinsize;
4655 fs_offset_t psbinsize;
4656 // IDirect3DVertexShader9 *vs = NULL;
4657 // IDirect3DPixelShader9 *ps = NULL;
4658 ID3DXBuffer *vslog = NULL;
4659 ID3DXBuffer *vsbuffer = NULL;
4660 ID3DXConstantTable *vsconstanttable = NULL;
4661 ID3DXBuffer *pslog = NULL;
4662 ID3DXBuffer *psbuffer = NULL;
4663 ID3DXConstantTable *psconstanttable = NULL;
4666 char temp[MAX_INPUTLINE];
4667 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4668 qboolean debugshader = gl_paranoid.integer != 0;
4669 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4670 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4673 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4674 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4676 if ((!vsbin && vertstring) || (!psbin && fragstring))
4678 const char* dllnames_d3dx9 [] =
4702 dllhandle_t d3dx9_dll = NULL;
4703 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4704 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4705 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4706 dllfunction_t d3dx9_dllfuncs[] =
4708 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
4709 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
4710 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
4713 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4715 DWORD shaderflags = 0;
4717 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4718 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4719 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4720 if (vertstring && vertstring[0])
4724 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4725 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4726 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4727 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4730 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4733 vsbinsize = vsbuffer->GetBufferSize();
4734 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4735 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4736 vsbuffer->Release();
4740 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4741 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4745 if (fragstring && fragstring[0])
4749 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4750 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4751 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4752 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4755 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4758 psbinsize = psbuffer->GetBufferSize();
4759 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4760 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4761 psbuffer->Release();
4765 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4766 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4770 Sys_UnloadLibrary(&d3dx9_dll);
4773 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4777 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4778 if (FAILED(vsresult))
4779 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4780 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4781 if (FAILED(psresult))
4782 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4784 // free the shader data
4785 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4786 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4789 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4792 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4793 int vertstring_length = 0;
4794 int geomstring_length = 0;
4795 int fragstring_length = 0;
4797 char *vertexstring, *geometrystring, *fragmentstring;
4798 char *vertstring, *geomstring, *fragstring;
4799 char permutationname[256];
4800 char cachename[256];
4801 int vertstrings_count = 0;
4802 int geomstrings_count = 0;
4803 int fragstrings_count = 0;
4804 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4805 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4806 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4811 p->vertexshader = NULL;
4812 p->pixelshader = NULL;
4814 permutationname[0] = 0;
4816 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
4817 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4818 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4820 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4821 strlcat(cachename, "hlsl/", sizeof(cachename));
4823 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4824 vertstrings_count = 0;
4825 geomstrings_count = 0;
4826 fragstrings_count = 0;
4827 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4828 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4829 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4831 // the first pretext is which type of shader to compile as
4832 // (later these will all be bound together as a program object)
4833 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4834 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4835 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4837 // the second pretext is the mode (for example a light source)
4838 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4839 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4840 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4841 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4842 strlcat(cachename, modeinfo->name, sizeof(cachename));
4844 // now add all the permutation pretexts
4845 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4847 if (permutation & (1<<i))
4849 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4850 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4851 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4852 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4853 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4857 // keep line numbers correct
4858 vertstrings_list[vertstrings_count++] = "\n";
4859 geomstrings_list[geomstrings_count++] = "\n";
4860 fragstrings_list[fragstrings_count++] = "\n";
4865 R_CompileShader_AddStaticParms(mode, permutation);
4866 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4867 vertstrings_count += shaderstaticparms_count;
4868 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4869 geomstrings_count += shaderstaticparms_count;
4870 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4871 fragstrings_count += shaderstaticparms_count;
4873 // replace spaces in the cachename with _ characters
4874 for (i = 0;cachename[i];i++)
4875 if (cachename[i] == ' ')
4878 // now append the shader text itself
4879 vertstrings_list[vertstrings_count++] = vertexstring;
4880 geomstrings_list[geomstrings_count++] = geometrystring;
4881 fragstrings_list[fragstrings_count++] = fragmentstring;
4883 // if any sources were NULL, clear the respective list
4885 vertstrings_count = 0;
4886 if (!geometrystring)
4887 geomstrings_count = 0;
4888 if (!fragmentstring)
4889 fragstrings_count = 0;
4891 vertstring_length = 0;
4892 for (i = 0;i < vertstrings_count;i++)
4893 vertstring_length += strlen(vertstrings_list[i]);
4894 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4895 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4896 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4898 geomstring_length = 0;
4899 for (i = 0;i < geomstrings_count;i++)
4900 geomstring_length += strlen(geomstrings_list[i]);
4901 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4902 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4903 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4905 fragstring_length = 0;
4906 for (i = 0;i < fragstrings_count;i++)
4907 fragstring_length += strlen(fragstrings_list[i]);
4908 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4909 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4910 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4912 // try to load the cached shader, or generate one
4913 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4915 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4916 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4918 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
4922 Mem_Free(vertstring);
4924 Mem_Free(geomstring);
4926 Mem_Free(fragstring);
4928 Mem_Free(vertexstring);
4930 Mem_Free(geometrystring);
4932 Mem_Free(fragmentstring);
4935 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4936 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4937 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);}
4938 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);}
4939 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);}
4940 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);}
4942 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4943 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4944 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);}
4945 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);}
4946 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);}
4947 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);}
4949 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4951 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4952 if (r_hlsl_permutation != perm)
4954 r_hlsl_permutation = perm;
4955 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4957 if (!r_hlsl_permutation->compiled)
4958 R_HLSL_CompilePermutation(perm, mode, permutation);
4959 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4961 // remove features until we find a valid permutation
4963 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4965 // reduce i more quickly whenever it would not remove any bits
4966 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4967 if (!(permutation & j))
4970 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4971 if (!r_hlsl_permutation->compiled)
4972 R_HLSL_CompilePermutation(perm, mode, permutation);
4973 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4976 if (i >= SHADERPERMUTATION_COUNT)
4978 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4979 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4980 return; // no bit left to clear, entire mode is broken
4984 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4985 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4987 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4988 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4989 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4993 void R_GLSL_Restart_f(void)
4995 unsigned int i, limit;
4996 if (glslshaderstring && glslshaderstring != builtinshaderstring)
4997 Mem_Free(glslshaderstring);
4998 glslshaderstring = NULL;
4999 if (cgshaderstring && cgshaderstring != builtincgshaderstring)
5000 Mem_Free(cgshaderstring);
5001 cgshaderstring = NULL;
5002 if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
5003 Mem_Free(hlslshaderstring);
5004 hlslshaderstring = NULL;
5005 switch(vid.renderpath)
5007 case RENDERPATH_D3D9:
5010 r_hlsl_permutation_t *p;
5011 r_hlsl_permutation = NULL;
5012 // cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5013 // cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5014 // cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5015 // cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5016 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
5017 for (i = 0;i < limit;i++)
5019 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
5021 if (p->vertexshader)
5022 IDirect3DVertexShader9_Release(p->vertexshader);
5024 IDirect3DPixelShader9_Release(p->pixelshader);
5025 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
5028 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
5032 case RENDERPATH_D3D10:
5033 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5035 case RENDERPATH_D3D11:
5036 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5038 case RENDERPATH_GL20:
5040 r_glsl_permutation_t *p;
5041 r_glsl_permutation = NULL;
5042 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
5043 for (i = 0;i < limit;i++)
5045 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
5047 GL_Backend_FreeProgram(p->program);
5048 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
5051 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5054 case RENDERPATH_CGGL:
5057 r_cg_permutation_t *p;
5058 r_cg_permutation = NULL;
5059 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5060 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5061 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5062 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5063 limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
5064 for (i = 0;i < limit;i++)
5066 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
5069 cgDestroyProgram(p->vprogram);
5071 cgDestroyProgram(p->fprogram);
5072 Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
5075 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5079 case RENDERPATH_GL13:
5080 case RENDERPATH_GL11:
5085 void R_GLSL_DumpShader_f(void)
5090 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
5093 FS_Print(file, "/* The engine may define the following macros:\n");
5094 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5095 for (i = 0;i < SHADERMODE_COUNT;i++)
5096 FS_Print(file, glslshadermodeinfo[i].pretext);
5097 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5098 FS_Print(file, shaderpermutationinfo[i].pretext);
5099 FS_Print(file, "*/\n");
5100 FS_Print(file, builtinshaderstring);
5102 Con_Printf("glsl/default.glsl written\n");
5105 Con_Printf("failed to write to glsl/default.glsl\n");
5108 file = FS_OpenRealFile("cg/default.cg", "w", false);
5111 FS_Print(file, "/* The engine may define the following macros:\n");
5112 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5113 for (i = 0;i < SHADERMODE_COUNT;i++)
5114 FS_Print(file, cgshadermodeinfo[i].pretext);
5115 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5116 FS_Print(file, shaderpermutationinfo[i].pretext);
5117 FS_Print(file, "*/\n");
5118 FS_Print(file, builtincgshaderstring);
5120 Con_Printf("cg/default.cg written\n");
5123 Con_Printf("failed to write to cg/default.cg\n");
5127 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
5130 FS_Print(file, "/* The engine may define the following macros:\n");
5131 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5132 for (i = 0;i < SHADERMODE_COUNT;i++)
5133 FS_Print(file, hlslshadermodeinfo[i].pretext);
5134 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5135 FS_Print(file, shaderpermutationinfo[i].pretext);
5136 FS_Print(file, "*/\n");
5137 FS_Print(file, builtincgshaderstring);
5139 Con_Printf("hlsl/default.hlsl written\n");
5142 Con_Printf("failed to write to hlsl/default.hlsl\n");
5146 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
5149 texturemode = GL_MODULATE;
5150 switch (vid.renderpath)
5152 case RENDERPATH_D3D9:
5154 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5155 R_Mesh_TexBind(GL20TU_FIRST , first );
5156 R_Mesh_TexBind(GL20TU_SECOND, second);
5159 case RENDERPATH_D3D10:
5160 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5162 case RENDERPATH_D3D11:
5163 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5165 case RENDERPATH_GL20:
5166 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5167 R_Mesh_TexBind(GL20TU_FIRST , first );
5168 R_Mesh_TexBind(GL20TU_SECOND, second);
5170 case RENDERPATH_CGGL:
5173 R_SetupShader_SetPermutationCG(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5174 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
5175 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
5178 case RENDERPATH_GL13:
5179 R_Mesh_TexBind(0, first );
5180 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
5181 R_Mesh_TexBind(1, second);
5183 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
5185 case RENDERPATH_GL11:
5186 R_Mesh_TexBind(0, first );
5191 void R_SetupShader_DepthOrShadow(void)
5193 switch (vid.renderpath)
5195 case RENDERPATH_D3D9:
5197 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5200 case RENDERPATH_D3D10:
5201 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5203 case RENDERPATH_D3D11:
5204 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5206 case RENDERPATH_GL20:
5207 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5209 case RENDERPATH_CGGL:
5211 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5214 case RENDERPATH_GL13:
5215 R_Mesh_TexBind(0, 0);
5216 R_Mesh_TexBind(1, 0);
5218 case RENDERPATH_GL11:
5219 R_Mesh_TexBind(0, 0);
5224 void R_SetupShader_ShowDepth(void)
5226 switch (vid.renderpath)
5228 case RENDERPATH_D3D9:
5230 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5233 case RENDERPATH_D3D10:
5234 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5236 case RENDERPATH_D3D11:
5237 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5239 case RENDERPATH_GL20:
5240 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5242 case RENDERPATH_CGGL:
5244 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5247 case RENDERPATH_GL13:
5249 case RENDERPATH_GL11:
5254 extern qboolean r_shadow_usingdeferredprepass;
5255 extern cvar_t r_shadow_deferred_8bitrange;
5256 extern rtexture_t *r_shadow_attenuationgradienttexture;
5257 extern rtexture_t *r_shadow_attenuation2dtexture;
5258 extern rtexture_t *r_shadow_attenuation3dtexture;
5259 extern qboolean r_shadow_usingshadowmap2d;
5260 extern qboolean r_shadow_usingshadowmaportho;
5261 extern float r_shadow_shadowmap_texturescale[2];
5262 extern float r_shadow_shadowmap_parameters[4];
5263 extern qboolean r_shadow_shadowmapvsdct;
5264 extern qboolean r_shadow_shadowmapsampler;
5265 extern int r_shadow_shadowmappcf;
5266 extern rtexture_t *r_shadow_shadowmap2dtexture;
5267 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5268 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5269 extern matrix4x4_t r_shadow_shadowmapmatrix;
5270 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5271 extern int r_shadow_prepass_width;
5272 extern int r_shadow_prepass_height;
5273 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5274 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5275 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
5276 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5277 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5278 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5280 // a blendfunc allows colormod if:
5281 // a) it can never keep the destination pixel invariant, or
5282 // b) it can keep the destination pixel invariant, and still can do so if colormodded
5283 // this is to prevent unintended side effects from colormod
5286 // IF there is a (s, sa) for which for all (d, da),
5287 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5288 // THEN, for this (s, sa) and all (colormod, d, da):
5289 // s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5290 // OBVIOUSLY, this means that
5291 // s*colormod * src(s*colormod, d, sa, da) = 0
5292 // dst(s*colormod, d, sa, da) = 1
5294 // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5296 // main condition to leave dst color invariant:
5297 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5299 // s * 0 + d * dst(s, d, sa, da) == d
5300 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5301 // => colormod is a problem for GL_SRC_COLOR only
5303 // s + d * dst(s, d, sa, da) == d
5305 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5306 // => colormod is never problematic for these
5307 // src == GL_SRC_COLOR:
5308 // s*s + d * dst(s, d, sa, da) == d
5310 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5311 // => colormod is never problematic for these
5312 // src == GL_ONE_MINUS_SRC_COLOR:
5313 // s*(1-s) + d * dst(s, d, sa, da) == d
5314 // => s == 0 or s == 1
5315 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5316 // => colormod is a problem for GL_SRC_COLOR only
5317 // src == GL_DST_COLOR
5318 // s*d + d * dst(s, d, sa, da) == d
5320 // => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5321 // => colormod is always a problem
5324 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5325 // => colormod is never problematic for these
5326 // => BUT, we do not know s! We must assume it is problematic
5327 // then... except in GL_ONE case, where we know all invariant
5329 // src == GL_ONE_MINUS_DST_COLOR
5330 // s*(1-d) + d * dst(s, d, sa, da) == d
5331 // => s == 0 (1-d is impossible to handle for our desired result)
5332 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5333 // => colormod is never problematic for these
5334 // src == GL_SRC_ALPHA
5335 // s*sa + d * dst(s, d, sa, da) == d
5336 // => s == 0, or sa == 0
5337 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5338 // => colormod breaks in the case GL_SRC_COLOR only
5339 // src == GL_ONE_MINUS_SRC_ALPHA
5340 // s*(1-sa) + d * dst(s, d, sa, da) == d
5341 // => s == 0, or sa == 1
5342 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5343 // => colormod breaks in the case GL_SRC_COLOR only
5344 // src == GL_DST_ALPHA
5345 // s*da + d * dst(s, d, sa, da) == d
5347 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5348 // => colormod is never problematic for these
5353 case GL_ONE_MINUS_SRC_COLOR:
5355 case GL_ONE_MINUS_SRC_ALPHA:
5356 if(dst == GL_SRC_COLOR)
5361 case GL_ONE_MINUS_DST_COLOR:
5363 case GL_ONE_MINUS_DST_ALPHA:
5373 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)
5375 // select a permutation of the lighting shader appropriate to this
5376 // combination of texture, entity, light source, and fogging, only use the
5377 // minimum features necessary to avoid wasting rendering time in the
5378 // fragment shader on features that are not being used
5379 unsigned int permutation = 0;
5380 unsigned int mode = 0;
5381 qboolean allow_colormod;
5382 static float dummy_colormod[3] = {1, 1, 1};
5383 float *colormod = rsurface.colormod;
5385 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5386 if (rsurfacepass == RSURFPASS_BACKGROUND)
5388 // distorted background
5389 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5391 mode = SHADERMODE_WATER;
5392 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
5393 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
5394 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
5396 // this is the right thing to do for wateralpha
5397 GL_BlendFunc(GL_ONE, GL_ZERO);
5398 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5402 // this is the right thing to do for entity alpha
5403 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5404 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5407 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5409 mode = SHADERMODE_REFRACTION;
5410 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5411 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5415 mode = SHADERMODE_GENERIC;
5416 permutation |= SHADERPERMUTATION_DIFFUSE;
5417 GL_BlendFunc(GL_ONE, GL_ZERO);
5418 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5420 GL_AlphaTest(false);
5422 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5424 if (r_glsl_offsetmapping.integer)
5426 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5427 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5428 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5429 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5430 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5432 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5433 if (r_glsl_offsetmapping_reliefmapping.integer)
5434 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5437 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5438 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5439 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5440 permutation |= SHADERPERMUTATION_ALPHAKILL;
5441 // normalmap (deferred prepass), may use alpha test on diffuse
5442 mode = SHADERMODE_DEFERREDGEOMETRY;
5443 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5444 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5445 GL_AlphaTest(false);
5446 GL_BlendFunc(GL_ONE, GL_ZERO);
5447 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5449 else if (rsurfacepass == RSURFPASS_RTLIGHT)
5451 if (r_glsl_offsetmapping.integer)
5453 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5454 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5455 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5456 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5457 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5459 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5460 if (r_glsl_offsetmapping_reliefmapping.integer)
5461 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5464 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5465 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5467 mode = SHADERMODE_LIGHTSOURCE;
5468 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5469 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5470 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5471 permutation |= SHADERPERMUTATION_CUBEFILTER;
5472 if (diffusescale > 0)
5473 permutation |= SHADERPERMUTATION_DIFFUSE;
5474 if (specularscale > 0)
5475 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5476 if (r_refdef.fogenabled)
5477 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5478 if (rsurface.texture->colormapping)
5479 permutation |= SHADERPERMUTATION_COLORMAPPING;
5480 if (r_shadow_usingshadowmap2d)
5482 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5483 if(r_shadow_shadowmapvsdct)
5484 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5486 if (r_shadow_shadowmapsampler)
5487 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5488 if (r_shadow_shadowmappcf > 1)
5489 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5490 else if (r_shadow_shadowmappcf)
5491 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5493 if (rsurface.texture->reflectmasktexture)
5494 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5495 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5496 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5497 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5499 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5501 if (r_glsl_offsetmapping.integer)
5503 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5504 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5505 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5506 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5507 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5509 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5510 if (r_glsl_offsetmapping_reliefmapping.integer)
5511 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5514 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5515 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5516 // unshaded geometry (fullbright or ambient model lighting)
5517 mode = SHADERMODE_FLATCOLOR;
5518 ambientscale = diffusescale = specularscale = 0;
5519 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5520 permutation |= SHADERPERMUTATION_GLOW;
5521 if (r_refdef.fogenabled)
5522 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5523 if (rsurface.texture->colormapping)
5524 permutation |= SHADERPERMUTATION_COLORMAPPING;
5525 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5527 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5528 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5530 if (r_shadow_shadowmapsampler)
5531 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5532 if (r_shadow_shadowmappcf > 1)
5533 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5534 else if (r_shadow_shadowmappcf)
5535 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5537 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5538 permutation |= SHADERPERMUTATION_REFLECTION;
5539 if (rsurface.texture->reflectmasktexture)
5540 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5541 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5542 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5543 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5545 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5547 if (r_glsl_offsetmapping.integer)
5549 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5550 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5551 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5552 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5553 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5555 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5556 if (r_glsl_offsetmapping_reliefmapping.integer)
5557 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5560 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5561 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5562 // directional model lighting
5563 mode = SHADERMODE_LIGHTDIRECTION;
5564 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5565 permutation |= SHADERPERMUTATION_GLOW;
5566 permutation |= SHADERPERMUTATION_DIFFUSE;
5567 if (specularscale > 0)
5568 permutation |= SHADERPERMUTATION_SPECULAR;
5569 if (r_refdef.fogenabled)
5570 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5571 if (rsurface.texture->colormapping)
5572 permutation |= SHADERPERMUTATION_COLORMAPPING;
5573 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5575 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5576 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5578 if (r_shadow_shadowmapsampler)
5579 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5580 if (r_shadow_shadowmappcf > 1)
5581 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5582 else if (r_shadow_shadowmappcf)
5583 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5585 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5586 permutation |= SHADERPERMUTATION_REFLECTION;
5587 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5588 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5589 if (rsurface.texture->reflectmasktexture)
5590 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5591 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5592 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5593 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5595 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5597 if (r_glsl_offsetmapping.integer)
5599 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5600 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5601 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5602 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5603 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5605 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5606 if (r_glsl_offsetmapping_reliefmapping.integer)
5607 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5610 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5611 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5612 // ambient model lighting
5613 mode = SHADERMODE_LIGHTDIRECTION;
5614 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5615 permutation |= SHADERPERMUTATION_GLOW;
5616 if (r_refdef.fogenabled)
5617 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5618 if (rsurface.texture->colormapping)
5619 permutation |= SHADERPERMUTATION_COLORMAPPING;
5620 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5622 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5623 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5625 if (r_shadow_shadowmapsampler)
5626 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5627 if (r_shadow_shadowmappcf > 1)
5628 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5629 else if (r_shadow_shadowmappcf)
5630 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5632 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5633 permutation |= SHADERPERMUTATION_REFLECTION;
5634 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5635 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5636 if (rsurface.texture->reflectmasktexture)
5637 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5638 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5639 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5640 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5644 if (r_glsl_offsetmapping.integer)
5646 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5647 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5648 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5649 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5650 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5652 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5653 if (r_glsl_offsetmapping_reliefmapping.integer)
5654 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5657 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5658 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5660 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5661 permutation |= SHADERPERMUTATION_GLOW;
5662 if (r_refdef.fogenabled)
5663 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5664 if (rsurface.texture->colormapping)
5665 permutation |= SHADERPERMUTATION_COLORMAPPING;
5666 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5668 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5669 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5671 if (r_shadow_shadowmapsampler)
5672 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5673 if (r_shadow_shadowmappcf > 1)
5674 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5675 else if (r_shadow_shadowmappcf)
5676 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5678 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5679 permutation |= SHADERPERMUTATION_REFLECTION;
5680 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5681 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5682 if (rsurface.texture->reflectmasktexture)
5683 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5684 if (FAKELIGHT_ENABLED)
5686 // fake lightmapping (q1bsp, q3bsp, fullbright map)
5687 mode = SHADERMODE_FAKELIGHT;
5688 permutation |= SHADERPERMUTATION_DIFFUSE;
5689 if (specularscale > 0)
5690 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5692 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5694 // deluxemapping (light direction texture)
5695 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5696 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5698 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5699 permutation |= SHADERPERMUTATION_DIFFUSE;
5700 if (specularscale > 0)
5701 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5703 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5705 // fake deluxemapping (uniform light direction in tangentspace)
5706 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5707 permutation |= SHADERPERMUTATION_DIFFUSE;
5708 if (specularscale > 0)
5709 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5711 else if (rsurface.uselightmaptexture)
5713 // ordinary lightmapping (q1bsp, q3bsp)
5714 mode = SHADERMODE_LIGHTMAP;
5718 // ordinary vertex coloring (q3bsp)
5719 mode = SHADERMODE_VERTEXCOLOR;
5721 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5722 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5723 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5726 colormod = dummy_colormod;
5727 switch(vid.renderpath)
5729 case RENDERPATH_D3D9:
5731 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);
5732 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5733 R_SetupShader_SetPermutationHLSL(mode, permutation);
5734 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5735 if (mode == SHADERMODE_LIGHTSOURCE)
5737 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5738 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5742 if (mode == SHADERMODE_LIGHTDIRECTION)
5744 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5747 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5748 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5749 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5750 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5751 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5753 if (mode == SHADERMODE_LIGHTSOURCE)
5755 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5756 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5757 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5758 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5759 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5761 // additive passes are only darkened by fog, not tinted
5762 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5763 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5767 if (mode == SHADERMODE_FLATCOLOR)
5769 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5771 else if (mode == SHADERMODE_LIGHTDIRECTION)
5773 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]);
5774 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5775 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);
5776 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);
5777 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5778 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5779 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5783 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5784 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5785 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);
5786 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);
5787 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5789 // additive passes are only darkened by fog, not tinted
5790 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5791 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5793 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5794 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);
5795 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5796 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5797 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5798 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5799 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5800 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5801 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5802 if (mode == SHADERMODE_WATER)
5803 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5805 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5806 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5807 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5808 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));
5809 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5810 if (rsurface.texture->pantstexture)
5811 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5813 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5814 if (rsurface.texture->shirttexture)
5815 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5817 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5818 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5819 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5820 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5821 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5822 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5823 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5824 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5826 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5827 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5828 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5829 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5830 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5831 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5832 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5833 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5834 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5835 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5836 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5837 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5838 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5839 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5840 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5841 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5842 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5843 if (rsurfacepass == RSURFPASS_BACKGROUND)
5845 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5846 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5847 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5851 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5853 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5854 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5855 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5856 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5857 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5859 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5860 if (rsurface.rtlight)
5862 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5863 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5868 case RENDERPATH_D3D10:
5869 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5871 case RENDERPATH_D3D11:
5872 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5874 case RENDERPATH_GL20:
5875 if (!vid.useinterleavedarrays)
5877 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);
5878 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5879 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5880 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5881 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5882 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5883 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5884 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5888 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);
5889 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5891 R_SetupShader_SetPermutationGLSL(mode, permutation);
5892 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5893 if (mode == SHADERMODE_LIGHTSOURCE)
5895 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5896 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5897 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5898 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5899 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5900 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);
5902 // additive passes are only darkened by fog, not tinted
5903 if (r_glsl_permutation->loc_FogColor >= 0)
5904 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5905 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5909 if (mode == SHADERMODE_FLATCOLOR)
5911 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5913 else if (mode == SHADERMODE_LIGHTDIRECTION)
5915 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 * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
5916 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]);
5917 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);
5918 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);
5919 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);
5920 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
5921 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]);
5925 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]);
5926 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]);
5927 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);
5928 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);
5929 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);
5931 // additive passes are only darkened by fog, not tinted
5932 if (r_glsl_permutation->loc_FogColor >= 0)
5934 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5935 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5937 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5939 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);
5940 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]);
5941 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]);
5942 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]);
5943 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]);
5944 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5945 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5946 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5947 if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2fARB(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5949 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5950 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5951 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5952 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]);
5953 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]);
5955 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5956 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));
5957 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5958 if (r_glsl_permutation->loc_Color_Pants >= 0)
5960 if (rsurface.texture->pantstexture)
5961 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5963 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5965 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5967 if (rsurface.texture->shirttexture)
5968 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5970 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5972 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]);
5973 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5974 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5975 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5976 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5977 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]);
5978 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5980 // if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_texture_white );
5981 // if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_texture_white );
5982 // if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS , r_texture_gammaramps );
5983 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5984 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5985 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5986 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5987 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5988 if (r_glsl_permutation->loc_Texture_SecondaryColor >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5989 if (r_glsl_permutation->loc_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5990 if (r_glsl_permutation->loc_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5991 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5992 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5993 if (r_glsl_permutation->loc_Texture_ReflectMask >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5994 if (r_glsl_permutation->loc_Texture_ReflectCube >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5995 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5996 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5997 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5998 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5999 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
6000 if (rsurfacepass == RSURFPASS_BACKGROUND)
6002 if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
6003 else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
6004 if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
6008 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
6010 // if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
6011 // if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
6012 if (r_glsl_permutation->loc_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
6013 if (r_glsl_permutation->loc_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
6014 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6016 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture );
6017 if (rsurface.rtlight)
6019 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
6020 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
6025 case RENDERPATH_CGGL:
6027 if (!vid.useinterleavedarrays)
6029 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);
6030 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
6031 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
6032 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
6033 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
6034 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
6035 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
6036 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
6040 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);
6041 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
6043 R_SetupShader_SetPermutationCG(mode, permutation);
6044 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
6045 if (mode == SHADERMODE_LIGHTSOURCE)
6047 if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
6048 if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6052 if (mode == SHADERMODE_LIGHTDIRECTION)
6054 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
6057 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
6058 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
6059 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
6060 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6061 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
6064 if (mode == SHADERMODE_LIGHTSOURCE)
6066 if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6067 if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
6068 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
6069 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
6070 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
6072 // additive passes are only darkened by fog, not tinted
6073 if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
6074 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6078 if (mode == SHADERMODE_FLATCOLOR)
6080 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
6082 else if (mode == SHADERMODE_LIGHTDIRECTION)
6084 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
6085 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
6086 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
6087 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
6088 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
6089 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
6090 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
6094 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
6095 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
6096 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
6097 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
6098 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
6100 // additive passes are only darkened by fog, not tinted
6101 if (r_cg_permutation->fp_FogColor)
6103 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6104 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
6106 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6109 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
6110 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
6111 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
6112 if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4f(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
6113 if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4f(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
6114 if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
6115 if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
6116 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6117 if (r_cg_permutation->fp_NormalmapScrollBlend) cgGLSetParameter2f(r_cg_permutation->fp_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
6119 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
6120 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
6121 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
6122 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
6123 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6124 if (r_cg_permutation->fp_Color_Pants)
6126 if (rsurface.texture->pantstexture)
6127 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6129 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
6132 if (r_cg_permutation->fp_Color_Shirt)
6134 if (rsurface.texture->shirttexture)
6135 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6137 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
6140 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
6141 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
6142 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
6143 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
6144 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
6145 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
6146 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6148 // if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_texture_white );CHECKCGERROR
6149 // if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_texture_white );CHECKCGERROR
6150 // if (r_cg_permutation->fp_Texture_GammaRamps ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps , r_texture_gammaramps );CHECKCGERROR
6151 if (r_cg_permutation->fp_Texture_Normal ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal , rsurface.texture->nmaptexture );CHECKCGERROR
6152 if (r_cg_permutation->fp_Texture_Color ) CG_BindTexture(r_cg_permutation->fp_Texture_Color , rsurface.texture->basetexture );CHECKCGERROR
6153 if (r_cg_permutation->fp_Texture_Gloss ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss , rsurface.texture->glosstexture );CHECKCGERROR
6154 if (r_cg_permutation->fp_Texture_Glow ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow , rsurface.texture->glowtexture );CHECKCGERROR
6155 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture );CHECKCGERROR
6156 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );CHECKCGERROR
6157 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );CHECKCGERROR
6158 if (r_cg_permutation->fp_Texture_SecondaryGlow ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );CHECKCGERROR
6159 if (r_cg_permutation->fp_Texture_Pants ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants , rsurface.texture->pantstexture );CHECKCGERROR
6160 if (r_cg_permutation->fp_Texture_Shirt ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt , rsurface.texture->shirttexture );CHECKCGERROR
6161 if (r_cg_permutation->fp_Texture_ReflectMask ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask , rsurface.texture->reflectmasktexture );CHECKCGERROR
6162 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
6163 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture );CHECKCGERROR
6164 if (r_cg_permutation->fp_Texture_FogMask ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask , r_texture_fogattenuation );CHECKCGERROR
6165 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
6166 if (r_cg_permutation->fp_Texture_Deluxemap ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
6167 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
6168 if (rsurfacepass == RSURFPASS_BACKGROUND)
6170 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
6171 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
6172 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
6176 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
6178 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
6179 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
6180 if (r_cg_permutation->fp_Texture_ScreenDiffuse ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );CHECKCGERROR
6181 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );CHECKCGERROR
6182 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6184 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
6185 if (rsurface.rtlight)
6187 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
6188 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
6195 case RENDERPATH_GL13:
6196 case RENDERPATH_GL11:
6201 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6203 // select a permutation of the lighting shader appropriate to this
6204 // combination of texture, entity, light source, and fogging, only use the
6205 // minimum features necessary to avoid wasting rendering time in the
6206 // fragment shader on features that are not being used
6207 unsigned int permutation = 0;
6208 unsigned int mode = 0;
6209 const float *lightcolorbase = rtlight->currentcolor;
6210 float ambientscale = rtlight->ambientscale;
6211 float diffusescale = rtlight->diffusescale;
6212 float specularscale = rtlight->specularscale;
6213 // this is the location of the light in view space
6214 vec3_t viewlightorigin;
6215 // this transforms from view space (camera) to light space (cubemap)
6216 matrix4x4_t viewtolight;
6217 matrix4x4_t lighttoview;
6218 float viewtolight16f[16];
6219 float range = 1.0f / r_shadow_deferred_8bitrange.value;
6221 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6222 if (rtlight->currentcubemap != r_texture_whitecube)
6223 permutation |= SHADERPERMUTATION_CUBEFILTER;
6224 if (diffusescale > 0)
6225 permutation |= SHADERPERMUTATION_DIFFUSE;
6226 if (specularscale > 0)
6227 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6228 if (r_shadow_usingshadowmap2d)
6230 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6231 if (r_shadow_shadowmapvsdct)
6232 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6234 if (r_shadow_shadowmapsampler)
6235 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6236 if (r_shadow_shadowmappcf > 1)
6237 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6238 else if (r_shadow_shadowmappcf)
6239 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6241 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6242 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6243 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6244 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6245 switch(vid.renderpath)
6247 case RENDERPATH_D3D9:
6249 R_SetupShader_SetPermutationHLSL(mode, permutation);
6250 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6251 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6252 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
6253 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
6254 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6255 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6256 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6257 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6258 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6259 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6261 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
6262 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
6263 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
6264 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
6265 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
6266 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
6269 case RENDERPATH_D3D10:
6270 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6272 case RENDERPATH_D3D11:
6273 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6275 case RENDERPATH_GL20:
6276 R_SetupShader_SetPermutationGLSL(mode, permutation);
6277 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6278 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
6279 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);
6280 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);
6281 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);
6282 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]);
6283 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]);
6284 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB( r_glsl_permutation->loc_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6285 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]);
6286 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6288 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
6289 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
6290 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
6291 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
6292 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
6293 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
6295 case RENDERPATH_CGGL:
6297 R_SetupShader_SetPermutationCG(mode, permutation);
6298 if (r_cg_permutation->fp_LightPosition ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6299 if (r_cg_permutation->fp_ViewToLight ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6300 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
6301 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
6302 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
6303 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
6304 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
6305 if (r_cg_permutation->fp_SpecularPower ) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6306 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
6307 if (r_cg_permutation->fp_PixelToScreenTexCoord ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6309 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
6310 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
6311 if (r_cg_permutation->fp_Texture_ScreenNormalMap ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
6312 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
6313 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
6314 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
6317 case RENDERPATH_GL13:
6318 case RENDERPATH_GL11:
6323 #define SKINFRAME_HASH 1024
6327 int loadsequence; // incremented each level change
6328 memexpandablearray_t array;
6329 skinframe_t *hash[SKINFRAME_HASH];
6332 r_skinframe_t r_skinframe;
6334 void R_SkinFrame_PrepareForPurge(void)
6336 r_skinframe.loadsequence++;
6337 // wrap it without hitting zero
6338 if (r_skinframe.loadsequence >= 200)
6339 r_skinframe.loadsequence = 1;
6342 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6346 // mark the skinframe as used for the purging code
6347 skinframe->loadsequence = r_skinframe.loadsequence;
6350 void R_SkinFrame_Purge(void)
6354 for (i = 0;i < SKINFRAME_HASH;i++)
6356 for (s = r_skinframe.hash[i];s;s = s->next)
6358 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6360 if (s->merged == s->base)
6362 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6363 R_PurgeTexture(s->stain );s->stain = NULL;
6364 R_PurgeTexture(s->merged);s->merged = NULL;
6365 R_PurgeTexture(s->base );s->base = NULL;
6366 R_PurgeTexture(s->pants );s->pants = NULL;
6367 R_PurgeTexture(s->shirt );s->shirt = NULL;
6368 R_PurgeTexture(s->nmap );s->nmap = NULL;
6369 R_PurgeTexture(s->gloss );s->gloss = NULL;
6370 R_PurgeTexture(s->glow );s->glow = NULL;
6371 R_PurgeTexture(s->fog );s->fog = NULL;
6372 R_PurgeTexture(s->reflect);s->reflect = NULL;
6373 s->loadsequence = 0;
6379 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6381 char basename[MAX_QPATH];
6383 Image_StripImageExtension(name, basename, sizeof(basename));
6385 if( last == NULL ) {
6387 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6388 item = r_skinframe.hash[hashindex];
6393 // linearly search through the hash bucket
6394 for( ; item ; item = item->next ) {
6395 if( !strcmp( item->basename, basename ) ) {
6402 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6406 char basename[MAX_QPATH];
6408 Image_StripImageExtension(name, basename, sizeof(basename));
6410 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6411 for (item = r_skinframe.hash[hashindex];item;item = item->next)
6412 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6416 rtexture_t *dyntexture;
6417 // check whether its a dynamic texture
6418 dyntexture = CL_GetDynTexture( basename );
6419 if (!add && !dyntexture)
6421 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6422 memset(item, 0, sizeof(*item));
6423 strlcpy(item->basename, basename, sizeof(item->basename));
6424 item->base = dyntexture; // either NULL or dyntexture handle
6425 item->textureflags = textureflags;
6426 item->comparewidth = comparewidth;
6427 item->compareheight = compareheight;
6428 item->comparecrc = comparecrc;
6429 item->next = r_skinframe.hash[hashindex];
6430 r_skinframe.hash[hashindex] = item;
6432 else if( item->base == NULL )
6434 rtexture_t *dyntexture;
6435 // check whether its a dynamic texture
6436 // 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]
6437 dyntexture = CL_GetDynTexture( basename );
6438 item->base = dyntexture; // either NULL or dyntexture handle
6441 R_SkinFrame_MarkUsed(item);
6445 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6447 unsigned long long avgcolor[5], wsum; \
6455 for(pix = 0; pix < cnt; ++pix) \
6458 for(comp = 0; comp < 3; ++comp) \
6460 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6463 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6465 for(comp = 0; comp < 3; ++comp) \
6466 avgcolor[comp] += getpixel * w; \
6469 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6470 avgcolor[4] += getpixel; \
6472 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6474 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6475 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6476 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6477 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6480 extern cvar_t gl_picmip;
6481 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6484 unsigned char *pixels;
6485 unsigned char *bumppixels;
6486 unsigned char *basepixels = NULL;
6487 int basepixels_width = 0;
6488 int basepixels_height = 0;
6489 skinframe_t *skinframe;
6490 rtexture_t *ddsbase = NULL;
6491 qboolean ddshasalpha = false;
6492 float ddsavgcolor[4];
6493 char basename[MAX_QPATH];
6494 int miplevel = R_PicmipForFlags(textureflags);
6495 int savemiplevel = miplevel;
6498 if (cls.state == ca_dedicated)
6501 // return an existing skinframe if already loaded
6502 // if loading of the first image fails, don't make a new skinframe as it
6503 // would cause all future lookups of this to be missing
6504 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6505 if (skinframe && skinframe->base)
6508 Image_StripImageExtension(name, basename, sizeof(basename));
6510 // check for DDS texture file first
6511 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6513 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6514 if (basepixels == NULL)
6518 // FIXME handle miplevel
6520 if (developer_loading.integer)
6521 Con_Printf("loading skin \"%s\"\n", name);
6523 // we've got some pixels to store, so really allocate this new texture now
6525 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6526 skinframe->stain = NULL;
6527 skinframe->merged = NULL;
6528 skinframe->base = NULL;
6529 skinframe->pants = NULL;
6530 skinframe->shirt = NULL;
6531 skinframe->nmap = NULL;
6532 skinframe->gloss = NULL;
6533 skinframe->glow = NULL;
6534 skinframe->fog = NULL;
6535 skinframe->reflect = NULL;
6536 skinframe->hasalpha = false;
6540 skinframe->base = ddsbase;
6541 skinframe->hasalpha = ddshasalpha;
6542 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6543 if (r_loadfog && skinframe->hasalpha)
6544 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6545 //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]);
6549 basepixels_width = image_width;
6550 basepixels_height = image_height;
6551 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);
6552 if (textureflags & TEXF_ALPHA)
6554 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6556 if (basepixels[j] < 255)
6558 skinframe->hasalpha = true;
6562 if (r_loadfog && skinframe->hasalpha)
6564 // has transparent pixels
6565 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6566 for (j = 0;j < image_width * image_height * 4;j += 4)
6571 pixels[j+3] = basepixels[j+3];
6573 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);
6577 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6578 //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]);
6579 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6580 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6581 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6582 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6587 mymiplevel = savemiplevel;
6588 if (r_loadnormalmap)
6589 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);
6590 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6592 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6593 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6594 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6595 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6598 // _norm is the name used by tenebrae and has been adopted as standard
6599 if (r_loadnormalmap && skinframe->nmap == NULL)
6601 mymiplevel = savemiplevel;
6602 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6604 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);
6608 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6610 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6611 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6612 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);
6614 Mem_Free(bumppixels);
6616 else if (r_shadow_bumpscale_basetexture.value > 0)
6618 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6619 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6620 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);
6623 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6624 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6627 // _luma is supported only for tenebrae compatibility
6628 // _glow is the preferred name
6629 mymiplevel = savemiplevel;
6630 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))))
6632 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);
6633 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6634 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6635 Mem_Free(pixels);pixels = NULL;
6638 mymiplevel = savemiplevel;
6639 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6641 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);
6642 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6643 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6648 mymiplevel = savemiplevel;
6649 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6651 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);
6652 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6653 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6658 mymiplevel = savemiplevel;
6659 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6661 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);
6662 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6663 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6668 mymiplevel = savemiplevel;
6669 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6671 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);
6672 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6673 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6679 Mem_Free(basepixels);
6684 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6685 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6688 unsigned char *temp1, *temp2;
6689 skinframe_t *skinframe;
6691 if (cls.state == ca_dedicated)
6694 // if already loaded just return it, otherwise make a new skinframe
6695 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6696 if (skinframe && skinframe->base)
6699 skinframe->stain = NULL;
6700 skinframe->merged = NULL;
6701 skinframe->base = NULL;
6702 skinframe->pants = NULL;
6703 skinframe->shirt = NULL;
6704 skinframe->nmap = NULL;
6705 skinframe->gloss = NULL;
6706 skinframe->glow = NULL;
6707 skinframe->fog = NULL;
6708 skinframe->reflect = NULL;
6709 skinframe->hasalpha = false;
6711 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6715 if (developer_loading.integer)
6716 Con_Printf("loading 32bit skin \"%s\"\n", name);
6718 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6720 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6721 temp2 = temp1 + width * height * 4;
6722 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6723 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);
6726 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6727 if (textureflags & TEXF_ALPHA)
6729 for (i = 3;i < width * height * 4;i += 4)
6731 if (skindata[i] < 255)
6733 skinframe->hasalpha = true;
6737 if (r_loadfog && skinframe->hasalpha)
6739 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6740 memcpy(fogpixels, skindata, width * height * 4);
6741 for (i = 0;i < width * height * 4;i += 4)
6742 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6743 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6744 Mem_Free(fogpixels);
6748 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6749 //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]);
6754 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6758 skinframe_t *skinframe;
6760 if (cls.state == ca_dedicated)
6763 // if already loaded just return it, otherwise make a new skinframe
6764 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6765 if (skinframe && skinframe->base)
6768 skinframe->stain = NULL;
6769 skinframe->merged = NULL;
6770 skinframe->base = NULL;
6771 skinframe->pants = NULL;
6772 skinframe->shirt = NULL;
6773 skinframe->nmap = NULL;
6774 skinframe->gloss = NULL;
6775 skinframe->glow = NULL;
6776 skinframe->fog = NULL;
6777 skinframe->reflect = NULL;
6778 skinframe->hasalpha = false;
6780 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6784 if (developer_loading.integer)
6785 Con_Printf("loading quake skin \"%s\"\n", name);
6787 // 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)
6788 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
6789 memcpy(skinframe->qpixels, skindata, width*height);
6790 skinframe->qwidth = width;
6791 skinframe->qheight = height;
6794 for (i = 0;i < width * height;i++)
6795 featuresmask |= palette_featureflags[skindata[i]];
6797 skinframe->hasalpha = false;
6798 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6799 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6800 skinframe->qgeneratemerged = true;
6801 skinframe->qgeneratebase = skinframe->qhascolormapping;
6802 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6804 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6805 //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]);
6810 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6814 unsigned char *skindata;
6816 if (!skinframe->qpixels)
6819 if (!skinframe->qhascolormapping)
6820 colormapped = false;
6824 if (!skinframe->qgeneratebase)
6829 if (!skinframe->qgeneratemerged)
6833 width = skinframe->qwidth;
6834 height = skinframe->qheight;
6835 skindata = skinframe->qpixels;
6837 if (skinframe->qgeneratenmap)
6839 unsigned char *temp1, *temp2;
6840 skinframe->qgeneratenmap = false;
6841 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6842 temp2 = temp1 + width * height * 4;
6843 // use either a custom palette or the quake palette
6844 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6845 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6846 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);
6850 if (skinframe->qgenerateglow)
6852 skinframe->qgenerateglow = false;
6853 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6858 skinframe->qgeneratebase = false;
6859 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);
6860 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6861 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6865 skinframe->qgeneratemerged = false;
6866 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);
6869 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6871 Mem_Free(skinframe->qpixels);
6872 skinframe->qpixels = NULL;
6876 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)
6879 skinframe_t *skinframe;
6881 if (cls.state == ca_dedicated)
6884 // if already loaded just return it, otherwise make a new skinframe
6885 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6886 if (skinframe && skinframe->base)
6889 skinframe->stain = NULL;
6890 skinframe->merged = NULL;
6891 skinframe->base = NULL;
6892 skinframe->pants = NULL;
6893 skinframe->shirt = NULL;
6894 skinframe->nmap = NULL;
6895 skinframe->gloss = NULL;
6896 skinframe->glow = NULL;
6897 skinframe->fog = NULL;
6898 skinframe->reflect = NULL;
6899 skinframe->hasalpha = false;
6901 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6905 if (developer_loading.integer)
6906 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6908 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6909 if (textureflags & TEXF_ALPHA)
6911 for (i = 0;i < width * height;i++)
6913 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6915 skinframe->hasalpha = true;
6919 if (r_loadfog && skinframe->hasalpha)
6920 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6923 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6924 //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]);
6929 skinframe_t *R_SkinFrame_LoadMissing(void)
6931 skinframe_t *skinframe;
6933 if (cls.state == ca_dedicated)
6936 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6937 skinframe->stain = NULL;
6938 skinframe->merged = NULL;
6939 skinframe->base = NULL;
6940 skinframe->pants = NULL;
6941 skinframe->shirt = NULL;
6942 skinframe->nmap = NULL;
6943 skinframe->gloss = NULL;
6944 skinframe->glow = NULL;
6945 skinframe->fog = NULL;
6946 skinframe->reflect = NULL;
6947 skinframe->hasalpha = false;
6949 skinframe->avgcolor[0] = rand() / RAND_MAX;
6950 skinframe->avgcolor[1] = rand() / RAND_MAX;
6951 skinframe->avgcolor[2] = rand() / RAND_MAX;
6952 skinframe->avgcolor[3] = 1;
6957 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6958 typedef struct suffixinfo_s
6961 qboolean flipx, flipy, flipdiagonal;
6964 static suffixinfo_t suffix[3][6] =
6967 {"px", false, false, false},
6968 {"nx", false, false, false},
6969 {"py", false, false, false},
6970 {"ny", false, false, false},
6971 {"pz", false, false, false},
6972 {"nz", false, false, false}
6975 {"posx", false, false, false},
6976 {"negx", false, false, false},
6977 {"posy", false, false, false},
6978 {"negy", false, false, false},
6979 {"posz", false, false, false},
6980 {"negz", false, false, false}
6983 {"rt", true, false, true},
6984 {"lf", false, true, true},
6985 {"ft", true, true, false},
6986 {"bk", false, false, false},
6987 {"up", true, false, true},
6988 {"dn", true, false, true}
6992 static int componentorder[4] = {0, 1, 2, 3};
6994 rtexture_t *R_LoadCubemap(const char *basename)
6996 int i, j, cubemapsize;
6997 unsigned char *cubemappixels, *image_buffer;
6998 rtexture_t *cubemaptexture;
7000 // must start 0 so the first loadimagepixels has no requested width/height
7002 cubemappixels = NULL;
7003 cubemaptexture = NULL;
7004 // keep trying different suffix groups (posx, px, rt) until one loads
7005 for (j = 0;j < 3 && !cubemappixels;j++)
7007 // load the 6 images in the suffix group
7008 for (i = 0;i < 6;i++)
7010 // generate an image name based on the base and and suffix
7011 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
7013 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
7015 // an image loaded, make sure width and height are equal
7016 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
7018 // if this is the first image to load successfully, allocate the cubemap memory
7019 if (!cubemappixels && image_width >= 1)
7021 cubemapsize = image_width;
7022 // note this clears to black, so unavailable sides are black
7023 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
7025 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
7027 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);
7030 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
7032 Mem_Free(image_buffer);
7036 // if a cubemap loaded, upload it
7039 if (developer_loading.integer)
7040 Con_Printf("loading cubemap \"%s\"\n", basename);
7042 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
7043 Mem_Free(cubemappixels);
7047 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
7048 if (developer_loading.integer)
7050 Con_Printf("(tried tried images ");
7051 for (j = 0;j < 3;j++)
7052 for (i = 0;i < 6;i++)
7053 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
7054 Con_Print(" and was unable to find any of them).\n");
7057 return cubemaptexture;
7060 rtexture_t *R_GetCubemap(const char *basename)
7063 for (i = 0;i < r_texture_numcubemaps;i++)
7064 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
7065 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
7066 if (i >= MAX_CUBEMAPS)
7067 return r_texture_whitecube;
7068 r_texture_numcubemaps++;
7069 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
7070 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
7071 return r_texture_cubemaps[i].texture;
7074 void R_FreeCubemaps(void)
7077 for (i = 0;i < r_texture_numcubemaps;i++)
7079 if (developer_loading.integer)
7080 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
7081 if (r_texture_cubemaps[i].texture)
7082 R_FreeTexture(r_texture_cubemaps[i].texture);
7084 r_texture_numcubemaps = 0;
7087 void R_Main_FreeViewCache(void)
7089 if (r_refdef.viewcache.entityvisible)
7090 Mem_Free(r_refdef.viewcache.entityvisible);
7091 if (r_refdef.viewcache.world_pvsbits)
7092 Mem_Free(r_refdef.viewcache.world_pvsbits);
7093 if (r_refdef.viewcache.world_leafvisible)
7094 Mem_Free(r_refdef.viewcache.world_leafvisible);
7095 if (r_refdef.viewcache.world_surfacevisible)
7096 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7097 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
7100 void R_Main_ResizeViewCache(void)
7102 int numentities = r_refdef.scene.numentities;
7103 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
7104 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
7105 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
7106 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
7107 if (r_refdef.viewcache.maxentities < numentities)
7109 r_refdef.viewcache.maxentities = numentities;
7110 if (r_refdef.viewcache.entityvisible)
7111 Mem_Free(r_refdef.viewcache.entityvisible);
7112 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
7114 if (r_refdef.viewcache.world_numclusters != numclusters)
7116 r_refdef.viewcache.world_numclusters = numclusters;
7117 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
7118 if (r_refdef.viewcache.world_pvsbits)
7119 Mem_Free(r_refdef.viewcache.world_pvsbits);
7120 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
7122 if (r_refdef.viewcache.world_numleafs != numleafs)
7124 r_refdef.viewcache.world_numleafs = numleafs;
7125 if (r_refdef.viewcache.world_leafvisible)
7126 Mem_Free(r_refdef.viewcache.world_leafvisible);
7127 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
7129 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
7131 r_refdef.viewcache.world_numsurfaces = numsurfaces;
7132 if (r_refdef.viewcache.world_surfacevisible)
7133 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7134 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
7138 extern rtexture_t *loadingscreentexture;
7139 void gl_main_start(void)
7141 loadingscreentexture = NULL;
7142 r_texture_blanknormalmap = NULL;
7143 r_texture_white = NULL;
7144 r_texture_grey128 = NULL;
7145 r_texture_black = NULL;
7146 r_texture_whitecube = NULL;
7147 r_texture_normalizationcube = NULL;
7148 r_texture_fogattenuation = NULL;
7149 r_texture_fogheighttexture = NULL;
7150 r_texture_gammaramps = NULL;
7151 r_texture_numcubemaps = 0;
7153 r_loaddds = r_texture_dds_load.integer;
7154 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
7156 switch(vid.renderpath)
7158 case RENDERPATH_GL20:
7159 case RENDERPATH_CGGL:
7160 case RENDERPATH_D3D9:
7161 case RENDERPATH_D3D10:
7162 case RENDERPATH_D3D11:
7163 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7164 Cvar_SetValueQuick(&gl_combine, 1);
7165 Cvar_SetValueQuick(&r_glsl, 1);
7166 r_loadnormalmap = true;
7170 case RENDERPATH_GL13:
7171 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7172 Cvar_SetValueQuick(&gl_combine, 1);
7173 Cvar_SetValueQuick(&r_glsl, 0);
7174 r_loadnormalmap = false;
7175 r_loadgloss = false;
7178 case RENDERPATH_GL11:
7179 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7180 Cvar_SetValueQuick(&gl_combine, 0);
7181 Cvar_SetValueQuick(&r_glsl, 0);
7182 r_loadnormalmap = false;
7183 r_loadgloss = false;
7189 R_FrameData_Reset();
7193 memset(r_queries, 0, sizeof(r_queries));
7195 r_qwskincache = NULL;
7196 r_qwskincache_size = 0;
7198 // set up r_skinframe loading system for textures
7199 memset(&r_skinframe, 0, sizeof(r_skinframe));
7200 r_skinframe.loadsequence = 1;
7201 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7203 r_main_texturepool = R_AllocTexturePool();
7204 R_BuildBlankTextures();
7206 if (vid.support.arb_texture_cube_map)
7209 R_BuildNormalizationCube();
7211 r_texture_fogattenuation = NULL;
7212 r_texture_fogheighttexture = NULL;
7213 r_texture_gammaramps = NULL;
7214 //r_texture_fogintensity = NULL;
7215 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7216 memset(&r_waterstate, 0, sizeof(r_waterstate));
7217 r_glsl_permutation = NULL;
7218 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7219 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7220 glslshaderstring = NULL;
7222 r_cg_permutation = NULL;
7223 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7224 Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7225 cgshaderstring = NULL;
7228 r_hlsl_permutation = NULL;
7229 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7230 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7231 hlslshaderstring = NULL;
7233 memset(&r_svbsp, 0, sizeof (r_svbsp));
7235 r_refdef.fogmasktable_density = 0;
7238 void gl_main_shutdown(void)
7241 R_FrameData_Reset();
7243 R_Main_FreeViewCache();
7245 switch(vid.renderpath)
7247 case RENDERPATH_GL11:
7248 case RENDERPATH_GL13:
7249 case RENDERPATH_GL20:
7250 case RENDERPATH_CGGL:
7252 qglDeleteQueriesARB(r_maxqueries, r_queries);
7254 case RENDERPATH_D3D9:
7255 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7257 case RENDERPATH_D3D10:
7258 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7260 case RENDERPATH_D3D11:
7261 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7267 memset(r_queries, 0, sizeof(r_queries));
7269 r_qwskincache = NULL;
7270 r_qwskincache_size = 0;
7272 // clear out the r_skinframe state
7273 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7274 memset(&r_skinframe, 0, sizeof(r_skinframe));
7277 Mem_Free(r_svbsp.nodes);
7278 memset(&r_svbsp, 0, sizeof (r_svbsp));
7279 R_FreeTexturePool(&r_main_texturepool);
7280 loadingscreentexture = NULL;
7281 r_texture_blanknormalmap = NULL;
7282 r_texture_white = NULL;
7283 r_texture_grey128 = NULL;
7284 r_texture_black = NULL;
7285 r_texture_whitecube = NULL;
7286 r_texture_normalizationcube = NULL;
7287 r_texture_fogattenuation = NULL;
7288 r_texture_fogheighttexture = NULL;
7289 r_texture_gammaramps = NULL;
7290 r_texture_numcubemaps = 0;
7291 //r_texture_fogintensity = NULL;
7292 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7293 memset(&r_waterstate, 0, sizeof(r_waterstate));
7296 r_glsl_permutation = NULL;
7297 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7298 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
7299 glslshaderstring = NULL;
7301 r_cg_permutation = NULL;
7302 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7303 Mem_ExpandableArray_FreeArray(&r_cg_permutationarray);
7304 cgshaderstring = NULL;
7307 r_hlsl_permutation = NULL;
7308 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7309 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
7310 hlslshaderstring = NULL;
7314 extern void CL_ParseEntityLump(char *entitystring);
7315 void gl_main_newmap(void)
7317 // FIXME: move this code to client
7318 char *entities, entname[MAX_QPATH];
7320 Mem_Free(r_qwskincache);
7321 r_qwskincache = NULL;
7322 r_qwskincache_size = 0;
7325 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7326 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7328 CL_ParseEntityLump(entities);
7332 if (cl.worldmodel->brush.entities)
7333 CL_ParseEntityLump(cl.worldmodel->brush.entities);
7335 R_Main_FreeViewCache();
7337 R_FrameData_Reset();
7340 void GL_Main_Init(void)
7342 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7344 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7345 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7346 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7347 if (gamemode == GAME_NEHAHRA)
7349 Cvar_RegisterVariable (&gl_fogenable);
7350 Cvar_RegisterVariable (&gl_fogdensity);
7351 Cvar_RegisterVariable (&gl_fogred);
7352 Cvar_RegisterVariable (&gl_foggreen);
7353 Cvar_RegisterVariable (&gl_fogblue);
7354 Cvar_RegisterVariable (&gl_fogstart);
7355 Cvar_RegisterVariable (&gl_fogend);
7356 Cvar_RegisterVariable (&gl_skyclip);
7358 Cvar_RegisterVariable(&r_motionblur);
7359 Cvar_RegisterVariable(&r_motionblur_maxblur);
7360 Cvar_RegisterVariable(&r_motionblur_bmin);
7361 Cvar_RegisterVariable(&r_motionblur_vmin);
7362 Cvar_RegisterVariable(&r_motionblur_vmax);
7363 Cvar_RegisterVariable(&r_motionblur_vcoeff);
7364 Cvar_RegisterVariable(&r_motionblur_randomize);
7365 Cvar_RegisterVariable(&r_damageblur);
7366 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7367 Cvar_RegisterVariable(&r_equalize_entities_minambient);
7368 Cvar_RegisterVariable(&r_equalize_entities_by);
7369 Cvar_RegisterVariable(&r_equalize_entities_to);
7370 Cvar_RegisterVariable(&r_depthfirst);
7371 Cvar_RegisterVariable(&r_useinfinitefarclip);
7372 Cvar_RegisterVariable(&r_farclip_base);
7373 Cvar_RegisterVariable(&r_farclip_world);
7374 Cvar_RegisterVariable(&r_nearclip);
7375 Cvar_RegisterVariable(&r_showbboxes);
7376 Cvar_RegisterVariable(&r_showsurfaces);
7377 Cvar_RegisterVariable(&r_showtris);
7378 Cvar_RegisterVariable(&r_shownormals);
7379 Cvar_RegisterVariable(&r_showlighting);
7380 Cvar_RegisterVariable(&r_showshadowvolumes);
7381 Cvar_RegisterVariable(&r_showcollisionbrushes);
7382 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7383 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7384 Cvar_RegisterVariable(&r_showdisabledepthtest);
7385 Cvar_RegisterVariable(&r_drawportals);
7386 Cvar_RegisterVariable(&r_drawentities);
7387 Cvar_RegisterVariable(&r_draw2d);
7388 Cvar_RegisterVariable(&r_drawworld);
7389 Cvar_RegisterVariable(&r_cullentities_trace);
7390 Cvar_RegisterVariable(&r_cullentities_trace_samples);
7391 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7392 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7393 Cvar_RegisterVariable(&r_cullentities_trace_delay);
7394 Cvar_RegisterVariable(&r_drawviewmodel);
7395 Cvar_RegisterVariable(&r_drawexteriormodel);
7396 Cvar_RegisterVariable(&r_speeds);
7397 Cvar_RegisterVariable(&r_fullbrights);
7398 Cvar_RegisterVariable(&r_wateralpha);
7399 Cvar_RegisterVariable(&r_dynamic);
7400 Cvar_RegisterVariable(&r_fakelight);
7401 Cvar_RegisterVariable(&r_fakelight_intensity);
7402 Cvar_RegisterVariable(&r_fullbright);
7403 Cvar_RegisterVariable(&r_shadows);
7404 Cvar_RegisterVariable(&r_shadows_darken);
7405 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7406 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7407 Cvar_RegisterVariable(&r_shadows_throwdistance);
7408 Cvar_RegisterVariable(&r_shadows_throwdirection);
7409 Cvar_RegisterVariable(&r_shadows_focus);
7410 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7411 Cvar_RegisterVariable(&r_q1bsp_skymasking);
7412 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7413 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7414 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7415 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7416 Cvar_RegisterVariable(&r_fog_exp2);
7417 Cvar_RegisterVariable(&r_drawfog);
7418 Cvar_RegisterVariable(&r_transparentdepthmasking);
7419 Cvar_RegisterVariable(&r_texture_dds_load);
7420 Cvar_RegisterVariable(&r_texture_dds_save);
7421 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7422 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7423 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7424 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7425 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7426 Cvar_RegisterVariable(&r_textureunits);
7427 Cvar_RegisterVariable(&gl_combine);
7428 Cvar_RegisterVariable(&r_glsl);
7429 Cvar_RegisterVariable(&r_glsl_deluxemapping);
7430 Cvar_RegisterVariable(&r_glsl_offsetmapping);
7431 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7432 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7433 Cvar_RegisterVariable(&r_glsl_postprocess);
7434 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7435 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7436 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7437 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7438 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
7439 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
7440 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
7441 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
7443 Cvar_RegisterVariable(&r_water);
7444 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7445 Cvar_RegisterVariable(&r_water_clippingplanebias);
7446 Cvar_RegisterVariable(&r_water_refractdistort);
7447 Cvar_RegisterVariable(&r_water_reflectdistort);
7448 Cvar_RegisterVariable(&r_water_scissormode);
7449 Cvar_RegisterVariable(&r_lerpsprites);
7450 Cvar_RegisterVariable(&r_lerpmodels);
7451 Cvar_RegisterVariable(&r_lerplightstyles);
7452 Cvar_RegisterVariable(&r_waterscroll);
7453 Cvar_RegisterVariable(&r_bloom);
7454 Cvar_RegisterVariable(&r_bloom_colorscale);
7455 Cvar_RegisterVariable(&r_bloom_brighten);
7456 Cvar_RegisterVariable(&r_bloom_blur);
7457 Cvar_RegisterVariable(&r_bloom_resolution);
7458 Cvar_RegisterVariable(&r_bloom_colorexponent);
7459 Cvar_RegisterVariable(&r_bloom_colorsubtract);
7460 Cvar_RegisterVariable(&r_hdr);
7461 Cvar_RegisterVariable(&r_hdr_scenebrightness);
7462 Cvar_RegisterVariable(&r_hdr_glowintensity);
7463 Cvar_RegisterVariable(&r_hdr_range);
7464 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7465 Cvar_RegisterVariable(&developer_texturelogging);
7466 Cvar_RegisterVariable(&gl_lightmaps);
7467 Cvar_RegisterVariable(&r_test);
7468 Cvar_RegisterVariable(&r_glsl_saturation);
7469 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
7470 Cvar_RegisterVariable(&r_framedatasize);
7471 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7472 Cvar_SetValue("r_fullbrights", 0);
7473 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7475 Cvar_RegisterVariable(&r_track_sprites);
7476 Cvar_RegisterVariable(&r_track_sprites_flags);
7477 Cvar_RegisterVariable(&r_track_sprites_scalew);
7478 Cvar_RegisterVariable(&r_track_sprites_scaleh);
7479 Cvar_RegisterVariable(&r_overheadsprites_perspective);
7480 Cvar_RegisterVariable(&r_overheadsprites_pushback);
7481 Cvar_RegisterVariable(&r_overheadsprites_scalex);
7482 Cvar_RegisterVariable(&r_overheadsprites_scaley);
7485 extern void R_Textures_Init(void);
7486 extern void GL_Draw_Init(void);
7487 extern void GL_Main_Init(void);
7488 extern void R_Shadow_Init(void);
7489 extern void R_Sky_Init(void);
7490 extern void GL_Surf_Init(void);
7491 extern void R_Particles_Init(void);
7492 extern void R_Explosion_Init(void);
7493 extern void gl_backend_init(void);
7494 extern void Sbar_Init(void);
7495 extern void R_LightningBeams_Init(void);
7496 extern void Mod_RenderInit(void);
7497 extern void Font_Init(void);
7499 void Render_Init(void)
7512 R_LightningBeams_Init();
7521 extern char *ENGINE_EXTENSIONS;
7524 gl_renderer = (const char *)qglGetString(GL_RENDERER);
7525 gl_vendor = (const char *)qglGetString(GL_VENDOR);
7526 gl_version = (const char *)qglGetString(GL_VERSION);
7527 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7531 if (!gl_platformextensions)
7532 gl_platformextensions = "";
7534 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7535 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7536 Con_Printf("GL_VERSION: %s\n", gl_version);
7537 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7538 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7540 VID_CheckExtensions();
7542 // LordHavoc: report supported extensions
7543 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7545 // clear to black (loading plaque will be seen over this)
7546 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7549 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7553 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7555 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7558 p = r_refdef.view.frustum + i;
7563 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7567 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7571 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7575 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7579 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7583 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7587 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7591 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7599 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7603 for (i = 0;i < numplanes;i++)
7610 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7614 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7618 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7622 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7626 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7630 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7634 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7638 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7646 //==================================================================================
7648 // LordHavoc: this stores temporary data used within the same frame
7650 typedef struct r_framedata_mem_s
7652 struct r_framedata_mem_s *purge; // older mem block to free on next frame
7653 size_t size; // how much usable space
7654 size_t current; // how much space in use
7655 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
7656 size_t wantedsize; // how much space was allocated
7657 unsigned char *data; // start of real data (16byte aligned)
7661 static r_framedata_mem_t *r_framedata_mem;
7663 void R_FrameData_Reset(void)
7665 while (r_framedata_mem)
7667 r_framedata_mem_t *next = r_framedata_mem->purge;
7668 Mem_Free(r_framedata_mem);
7669 r_framedata_mem = next;
7673 void R_FrameData_Resize(void)
7676 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7677 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
7678 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
7680 r_framedata_mem_t *newmem = Mem_Alloc(r_main_mempool, wantedsize);
7681 newmem->wantedsize = wantedsize;
7682 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
7683 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
7684 newmem->current = 0;
7686 newmem->purge = r_framedata_mem;
7687 r_framedata_mem = newmem;
7691 void R_FrameData_NewFrame(void)
7693 R_FrameData_Resize();
7694 if (!r_framedata_mem)
7696 // if we ran out of space on the last frame, free the old memory now
7697 while (r_framedata_mem->purge)
7699 // repeatedly remove the second item in the list, leaving only head
7700 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
7701 Mem_Free(r_framedata_mem->purge);
7702 r_framedata_mem->purge = next;
7704 // reset the current mem pointer
7705 r_framedata_mem->current = 0;
7706 r_framedata_mem->mark = 0;
7709 void *R_FrameData_Alloc(size_t size)
7713 // align to 16 byte boundary - the data pointer is already aligned, so we
7714 // only need to ensure the size of every allocation is also aligned
7715 size = (size + 15) & ~15;
7717 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
7719 // emergency - we ran out of space, allocate more memory
7720 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
7721 R_FrameData_Resize();
7724 data = r_framedata_mem->data + r_framedata_mem->current;
7725 r_framedata_mem->current += size;
7727 // count the usage for stats
7728 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
7729 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
7731 return (void *)data;
7734 void *R_FrameData_Store(size_t size, void *data)
7736 void *d = R_FrameData_Alloc(size);
7738 memcpy(d, data, size);
7742 void R_FrameData_SetMark(void)
7744 if (!r_framedata_mem)
7746 r_framedata_mem->mark = r_framedata_mem->current;
7749 void R_FrameData_ReturnToMark(void)
7751 if (!r_framedata_mem)
7753 r_framedata_mem->current = r_framedata_mem->mark;
7756 //==================================================================================
7758 // LordHavoc: animcache originally written by Echon, rewritten since then
7761 * Animation cache prevents re-generating mesh data for an animated model
7762 * multiple times in one frame for lighting, shadowing, reflections, etc.
7765 void R_AnimCache_Free(void)
7769 void R_AnimCache_ClearCache(void)
7772 entity_render_t *ent;
7774 for (i = 0;i < r_refdef.scene.numentities;i++)
7776 ent = r_refdef.scene.entities[i];
7777 ent->animcache_vertex3f = NULL;
7778 ent->animcache_normal3f = NULL;
7779 ent->animcache_svector3f = NULL;
7780 ent->animcache_tvector3f = NULL;
7781 ent->animcache_vertexmesh = NULL;
7782 ent->animcache_vertex3fbuffer = NULL;
7783 ent->animcache_vertexmeshbuffer = NULL;
7787 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7791 // check if we need the meshbuffers
7792 if (!vid.useinterleavedarrays)
7795 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7796 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7797 // TODO: upload vertex3f buffer?
7798 if (ent->animcache_vertexmesh)
7800 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7801 for (i = 0;i < numvertices;i++)
7802 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7803 if (ent->animcache_svector3f)
7804 for (i = 0;i < numvertices;i++)
7805 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7806 if (ent->animcache_tvector3f)
7807 for (i = 0;i < numvertices;i++)
7808 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7809 if (ent->animcache_normal3f)
7810 for (i = 0;i < numvertices;i++)
7811 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7812 // TODO: upload vertexmeshbuffer?
7816 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7818 dp_model_t *model = ent->model;
7820 // see if it's already cached this frame
7821 if (ent->animcache_vertex3f)
7823 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7824 if (wantnormals || wanttangents)
7826 if (ent->animcache_normal3f)
7827 wantnormals = false;
7828 if (ent->animcache_svector3f)
7829 wanttangents = false;
7830 if (wantnormals || wanttangents)
7832 numvertices = model->surfmesh.num_vertices;
7834 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7837 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7838 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7840 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7841 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7847 // see if this ent is worth caching
7848 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7850 // get some memory for this entity and generate mesh data
7851 numvertices = model->surfmesh.num_vertices;
7852 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7854 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7857 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7858 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7860 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7861 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7866 void R_AnimCache_CacheVisibleEntities(void)
7869 qboolean wantnormals = true;
7870 qboolean wanttangents = !r_showsurfaces.integer;
7872 switch(vid.renderpath)
7874 case RENDERPATH_GL20:
7875 case RENDERPATH_CGGL:
7876 case RENDERPATH_D3D9:
7877 case RENDERPATH_D3D10:
7878 case RENDERPATH_D3D11:
7880 case RENDERPATH_GL13:
7881 case RENDERPATH_GL11:
7882 wanttangents = false;
7886 if (r_shownormals.integer)
7887 wanttangents = wantnormals = true;
7889 // TODO: thread this
7890 // NOTE: R_PrepareRTLights() also caches entities
7892 for (i = 0;i < r_refdef.scene.numentities;i++)
7893 if (r_refdef.viewcache.entityvisible[i])
7894 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7897 //==================================================================================
7899 static void R_View_UpdateEntityLighting (void)
7902 entity_render_t *ent;
7903 vec3_t tempdiffusenormal, avg;
7904 vec_t f, fa, fd, fdd;
7905 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7907 for (i = 0;i < r_refdef.scene.numentities;i++)
7909 ent = r_refdef.scene.entities[i];
7911 // skip unseen models
7912 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7916 if (ent->model && ent->model->brush.num_leafs)
7918 // TODO: use modellight for r_ambient settings on world?
7919 VectorSet(ent->modellight_ambient, 0, 0, 0);
7920 VectorSet(ent->modellight_diffuse, 0, 0, 0);
7921 VectorSet(ent->modellight_lightdir, 0, 0, 1);
7925 // fetch the lighting from the worldmodel data
7926 VectorClear(ent->modellight_ambient);
7927 VectorClear(ent->modellight_diffuse);
7928 VectorClear(tempdiffusenormal);
7929 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7932 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7934 // complete lightning for lit sprites
7935 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
7936 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
7938 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
7939 org[2] = org[2] + r_overheadsprites_pushback.value;
7940 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, ent->modellight_lightdir, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
7943 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7945 if(ent->flags & RENDER_EQUALIZE)
7947 // first fix up ambient lighting...
7948 if(r_equalize_entities_minambient.value > 0)
7950 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7953 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7954 if(fa < r_equalize_entities_minambient.value * fd)
7957 // fa'/fd' = minambient
7958 // fa'+0.25*fd' = fa+0.25*fd
7960 // fa' = fd' * minambient
7961 // fd'*(0.25+minambient) = fa+0.25*fd
7963 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7964 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7966 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7967 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
7968 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7969 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7974 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7976 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
7977 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7981 // adjust brightness and saturation to target
7982 avg[0] = avg[1] = avg[2] = fa / f;
7983 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
7984 avg[0] = avg[1] = avg[2] = fd / f;
7985 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
7991 VectorSet(ent->modellight_ambient, 1, 1, 1);
7993 // move the light direction into modelspace coordinates for lighting code
7994 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7995 if(VectorLength2(ent->modellight_lightdir) == 0)
7996 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7997 VectorNormalize(ent->modellight_lightdir);
8001 #define MAX_LINEOFSIGHTTRACES 64
8003 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
8006 vec3_t boxmins, boxmaxs;
8009 dp_model_t *model = r_refdef.scene.worldmodel;
8011 if (!model || !model->brush.TraceLineOfSight)
8014 // expand the box a little
8015 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
8016 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
8017 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
8018 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
8019 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
8020 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
8022 // return true if eye is inside enlarged box
8023 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
8027 VectorCopy(eye, start);
8028 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
8029 if (model->brush.TraceLineOfSight(model, start, end))
8032 // try various random positions
8033 for (i = 0;i < numsamples;i++)
8035 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
8036 if (model->brush.TraceLineOfSight(model, start, end))
8044 static void R_View_UpdateEntityVisible (void)
8049 entity_render_t *ent;
8051 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8052 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8053 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
8054 : RENDER_EXTERIORMODEL;
8055 if (!r_drawviewmodel.integer)
8056 renderimask |= RENDER_VIEWMODEL;
8057 if (!r_drawexteriormodel.integer)
8058 renderimask |= RENDER_EXTERIORMODEL;
8059 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
8061 // worldmodel can check visibility
8062 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
8063 for (i = 0;i < r_refdef.scene.numentities;i++)
8065 ent = r_refdef.scene.entities[i];
8066 if (!(ent->flags & renderimask))
8067 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)))
8068 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))
8069 r_refdef.viewcache.entityvisible[i] = true;
8071 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
8072 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
8074 for (i = 0;i < r_refdef.scene.numentities;i++)
8076 ent = r_refdef.scene.entities[i];
8077 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
8079 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
8081 continue; // temp entities do pvs only
8082 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
8083 ent->last_trace_visibility = realtime;
8084 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
8085 r_refdef.viewcache.entityvisible[i] = 0;
8092 // no worldmodel or it can't check visibility
8093 for (i = 0;i < r_refdef.scene.numentities;i++)
8095 ent = r_refdef.scene.entities[i];
8096 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));
8101 /// only used if skyrendermasked, and normally returns false
8102 int R_DrawBrushModelsSky (void)
8105 entity_render_t *ent;
8108 for (i = 0;i < r_refdef.scene.numentities;i++)
8110 if (!r_refdef.viewcache.entityvisible[i])
8112 ent = r_refdef.scene.entities[i];
8113 if (!ent->model || !ent->model->DrawSky)
8115 ent->model->DrawSky(ent);
8121 static void R_DrawNoModel(entity_render_t *ent);
8122 static void R_DrawModels(void)
8125 entity_render_t *ent;
8127 for (i = 0;i < r_refdef.scene.numentities;i++)
8129 if (!r_refdef.viewcache.entityvisible[i])
8131 ent = r_refdef.scene.entities[i];
8132 r_refdef.stats.entities++;
8133 if (ent->model && ent->model->Draw != NULL)
8134 ent->model->Draw(ent);
8140 static void R_DrawModelsDepth(void)
8143 entity_render_t *ent;
8145 for (i = 0;i < r_refdef.scene.numentities;i++)
8147 if (!r_refdef.viewcache.entityvisible[i])
8149 ent = r_refdef.scene.entities[i];
8150 if (ent->model && ent->model->DrawDepth != NULL)
8151 ent->model->DrawDepth(ent);
8155 static void R_DrawModelsDebug(void)
8158 entity_render_t *ent;
8160 for (i = 0;i < r_refdef.scene.numentities;i++)
8162 if (!r_refdef.viewcache.entityvisible[i])
8164 ent = r_refdef.scene.entities[i];
8165 if (ent->model && ent->model->DrawDebug != NULL)
8166 ent->model->DrawDebug(ent);
8170 static void R_DrawModelsAddWaterPlanes(void)
8173 entity_render_t *ent;
8175 for (i = 0;i < r_refdef.scene.numentities;i++)
8177 if (!r_refdef.viewcache.entityvisible[i])
8179 ent = r_refdef.scene.entities[i];
8180 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
8181 ent->model->DrawAddWaterPlanes(ent);
8185 static void R_View_SetFrustum(const int *scissor)
8188 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
8189 vec3_t forward, left, up, origin, v;
8193 // flipped x coordinates (because x points left here)
8194 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8195 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8197 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
8198 switch(vid.renderpath)
8200 case RENDERPATH_D3D9:
8201 case RENDERPATH_D3D10:
8202 case RENDERPATH_D3D11:
8203 // non-flipped y coordinates
8204 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8205 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8207 case RENDERPATH_GL11:
8208 case RENDERPATH_GL13:
8209 case RENDERPATH_GL20:
8210 case RENDERPATH_CGGL:
8211 // non-flipped y coordinates
8212 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8213 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8218 // we can't trust r_refdef.view.forward and friends in reflected scenes
8219 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
8222 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
8223 r_refdef.view.frustum[0].normal[1] = 0 - 0;
8224 r_refdef.view.frustum[0].normal[2] = -1 - 0;
8225 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
8226 r_refdef.view.frustum[1].normal[1] = 0 + 0;
8227 r_refdef.view.frustum[1].normal[2] = -1 + 0;
8228 r_refdef.view.frustum[2].normal[0] = 0 - 0;
8229 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
8230 r_refdef.view.frustum[2].normal[2] = -1 - 0;
8231 r_refdef.view.frustum[3].normal[0] = 0 + 0;
8232 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
8233 r_refdef.view.frustum[3].normal[2] = -1 + 0;
8237 zNear = r_refdef.nearclip;
8238 nudge = 1.0 - 1.0 / (1<<23);
8239 r_refdef.view.frustum[4].normal[0] = 0 - 0;
8240 r_refdef.view.frustum[4].normal[1] = 0 - 0;
8241 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
8242 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
8243 r_refdef.view.frustum[5].normal[0] = 0 + 0;
8244 r_refdef.view.frustum[5].normal[1] = 0 + 0;
8245 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
8246 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
8252 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8253 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8254 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8255 r_refdef.view.frustum[0].dist = m[15] - m[12];
8257 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8258 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8259 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8260 r_refdef.view.frustum[1].dist = m[15] + m[12];
8262 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8263 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8264 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8265 r_refdef.view.frustum[2].dist = m[15] - m[13];
8267 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8268 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8269 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8270 r_refdef.view.frustum[3].dist = m[15] + m[13];
8272 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8273 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8274 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8275 r_refdef.view.frustum[4].dist = m[15] - m[14];
8277 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8278 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8279 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8280 r_refdef.view.frustum[5].dist = m[15] + m[14];
8283 if (r_refdef.view.useperspective)
8285 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8286 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]);
8287 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]);
8288 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]);
8289 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]);
8291 // then the normals from the corners relative to origin
8292 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
8293 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
8294 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
8295 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
8297 // in a NORMAL view, forward cross left == up
8298 // in a REFLECTED view, forward cross left == down
8299 // so our cross products above need to be adjusted for a left handed coordinate system
8300 CrossProduct(forward, left, v);
8301 if(DotProduct(v, up) < 0)
8303 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
8304 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
8305 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
8306 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
8309 // Leaving those out was a mistake, those were in the old code, and they
8310 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8311 // I couldn't reproduce it after adding those normalizations. --blub
8312 VectorNormalize(r_refdef.view.frustum[0].normal);
8313 VectorNormalize(r_refdef.view.frustum[1].normal);
8314 VectorNormalize(r_refdef.view.frustum[2].normal);
8315 VectorNormalize(r_refdef.view.frustum[3].normal);
8317 // make the corners absolute
8318 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
8319 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
8320 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
8321 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
8324 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8326 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8327 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8328 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8329 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8330 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8334 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8335 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8336 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8337 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8338 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8339 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8340 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8341 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8342 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8343 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8345 r_refdef.view.numfrustumplanes = 5;
8347 if (r_refdef.view.useclipplane)
8349 r_refdef.view.numfrustumplanes = 6;
8350 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8353 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8354 PlaneClassify(r_refdef.view.frustum + i);
8356 // LordHavoc: note to all quake engine coders, Quake had a special case
8357 // for 90 degrees which assumed a square view (wrong), so I removed it,
8358 // Quake2 has it disabled as well.
8360 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8361 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8362 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8363 //PlaneClassify(&frustum[0]);
8365 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8366 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8367 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8368 //PlaneClassify(&frustum[1]);
8370 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8371 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8372 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8373 //PlaneClassify(&frustum[2]);
8375 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8376 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8377 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8378 //PlaneClassify(&frustum[3]);
8381 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8382 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8383 //PlaneClassify(&frustum[4]);
8386 void R_View_UpdateWithScissor(const int *myscissor)
8388 R_Main_ResizeViewCache();
8389 R_View_SetFrustum(myscissor);
8390 R_View_WorldVisibility(r_refdef.view.useclipplane);
8391 R_View_UpdateEntityVisible();
8392 R_View_UpdateEntityLighting();
8395 void R_View_Update(void)
8397 R_Main_ResizeViewCache();
8398 R_View_SetFrustum(NULL);
8399 R_View_WorldVisibility(r_refdef.view.useclipplane);
8400 R_View_UpdateEntityVisible();
8401 R_View_UpdateEntityLighting();
8404 void R_SetupView(qboolean allowwaterclippingplane)
8406 const float *customclipplane = NULL;
8408 if (r_refdef.view.useclipplane && allowwaterclippingplane)
8410 // LordHavoc: couldn't figure out how to make this approach the
8411 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8412 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8413 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8414 dist = r_refdef.view.clipplane.dist;
8415 plane[0] = r_refdef.view.clipplane.normal[0];
8416 plane[1] = r_refdef.view.clipplane.normal[1];
8417 plane[2] = r_refdef.view.clipplane.normal[2];
8419 customclipplane = plane;
8422 if (!r_refdef.view.useperspective)
8423 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);
8424 else if (vid.stencil && r_useinfinitefarclip.integer)
8425 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);
8427 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);
8428 R_SetViewport(&r_refdef.view.viewport);
8431 void R_EntityMatrix(const matrix4x4_t *matrix)
8433 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8435 gl_modelmatrixchanged = false;
8436 gl_modelmatrix = *matrix;
8437 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8438 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8439 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8440 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8442 switch(vid.renderpath)
8444 case RENDERPATH_D3D9:
8446 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8447 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8450 case RENDERPATH_D3D10:
8451 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8453 case RENDERPATH_D3D11:
8454 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8456 case RENDERPATH_GL20:
8457 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8458 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8459 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8461 case RENDERPATH_CGGL:
8464 if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8465 if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8466 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8469 case RENDERPATH_GL13:
8470 case RENDERPATH_GL11:
8471 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8477 void R_ResetViewRendering2D(void)
8479 r_viewport_t viewport;
8482 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8483 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);
8484 R_SetViewport(&viewport);
8485 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8486 GL_Color(1, 1, 1, 1);
8487 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8488 GL_BlendFunc(GL_ONE, GL_ZERO);
8489 GL_AlphaTest(false);
8490 GL_ScissorTest(false);
8491 GL_DepthMask(false);
8492 GL_DepthRange(0, 1);
8493 GL_DepthTest(false);
8494 GL_DepthFunc(GL_LEQUAL);
8495 R_EntityMatrix(&identitymatrix);
8496 R_Mesh_ResetTextureState();
8497 GL_PolygonOffset(0, 0);
8498 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8499 switch(vid.renderpath)
8501 case RENDERPATH_GL11:
8502 case RENDERPATH_GL13:
8503 case RENDERPATH_GL20:
8504 case RENDERPATH_CGGL:
8505 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8507 case RENDERPATH_D3D9:
8508 case RENDERPATH_D3D10:
8509 case RENDERPATH_D3D11:
8512 GL_CullFace(GL_NONE);
8515 void R_ResetViewRendering3D(void)
8520 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8521 GL_Color(1, 1, 1, 1);
8522 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8523 GL_BlendFunc(GL_ONE, GL_ZERO);
8524 GL_AlphaTest(false);
8525 GL_ScissorTest(true);
8527 GL_DepthRange(0, 1);
8529 GL_DepthFunc(GL_LEQUAL);
8530 R_EntityMatrix(&identitymatrix);
8531 R_Mesh_ResetTextureState();
8532 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8533 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8534 switch(vid.renderpath)
8536 case RENDERPATH_GL11:
8537 case RENDERPATH_GL13:
8538 case RENDERPATH_GL20:
8539 case RENDERPATH_CGGL:
8540 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8542 case RENDERPATH_D3D9:
8543 case RENDERPATH_D3D10:
8544 case RENDERPATH_D3D11:
8547 GL_CullFace(r_refdef.view.cullface_back);
8552 R_RenderView_UpdateViewVectors
8555 static void R_RenderView_UpdateViewVectors(void)
8557 // break apart the view matrix into vectors for various purposes
8558 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8559 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8560 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8561 VectorNegate(r_refdef.view.left, r_refdef.view.right);
8562 // make an inverted copy of the view matrix for tracking sprites
8563 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8566 void R_RenderScene(void);
8567 void R_RenderWaterPlanes(void);
8569 static void R_Water_StartFrame(void)
8572 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8573 r_waterstate_waterplane_t *p;
8575 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8578 switch(vid.renderpath)
8580 case RENDERPATH_GL20:
8581 case RENDERPATH_CGGL:
8582 case RENDERPATH_D3D9:
8583 case RENDERPATH_D3D10:
8584 case RENDERPATH_D3D11:
8586 case RENDERPATH_GL13:
8587 case RENDERPATH_GL11:
8591 // set waterwidth and waterheight to the water resolution that will be
8592 // used (often less than the screen resolution for faster rendering)
8593 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8594 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8596 // calculate desired texture sizes
8597 // can't use water if the card does not support the texture size
8598 if (!r_water.integer || r_showsurfaces.integer)
8599 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8600 else if (vid.support.arb_texture_non_power_of_two)
8602 texturewidth = waterwidth;
8603 textureheight = waterheight;
8604 camerawidth = waterwidth;
8605 cameraheight = waterheight;
8609 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
8610 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
8611 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
8612 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
8615 // allocate textures as needed
8616 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8618 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8619 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8621 if (p->texture_refraction)
8622 R_FreeTexture(p->texture_refraction);
8623 p->texture_refraction = NULL;
8624 if (p->texture_reflection)
8625 R_FreeTexture(p->texture_reflection);
8626 p->texture_reflection = NULL;
8627 if (p->texture_camera)
8628 R_FreeTexture(p->texture_camera);
8629 p->texture_camera = NULL;
8631 memset(&r_waterstate, 0, sizeof(r_waterstate));
8632 r_waterstate.texturewidth = texturewidth;
8633 r_waterstate.textureheight = textureheight;
8634 r_waterstate.camerawidth = camerawidth;
8635 r_waterstate.cameraheight = cameraheight;
8638 if (r_waterstate.texturewidth)
8640 r_waterstate.enabled = true;
8642 // when doing a reduced render (HDR) we want to use a smaller area
8643 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8644 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8646 // set up variables that will be used in shader setup
8647 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8648 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8649 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8650 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8653 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8654 r_waterstate.numwaterplanes = 0;
8657 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8659 int triangleindex, planeindex;
8665 r_waterstate_waterplane_t *p;
8666 texture_t *t = R_GetCurrentTexture(surface->texture);
8668 // just use the first triangle with a valid normal for any decisions
8669 VectorClear(normal);
8670 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8672 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8673 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8674 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8675 TriangleNormal(vert[0], vert[1], vert[2], normal);
8676 if (VectorLength2(normal) >= 0.001)
8680 VectorCopy(normal, plane.normal);
8681 VectorNormalize(plane.normal);
8682 plane.dist = DotProduct(vert[0], plane.normal);
8683 PlaneClassify(&plane);
8684 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8686 // skip backfaces (except if nocullface is set)
8687 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8689 VectorNegate(plane.normal, plane.normal);
8691 PlaneClassify(&plane);
8695 // find a matching plane if there is one
8696 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8697 if(p->camera_entity == t->camera_entity)
8698 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8700 if (planeindex >= r_waterstate.maxwaterplanes)
8701 return; // nothing we can do, out of planes
8703 // if this triangle does not fit any known plane rendered this frame, add one
8704 if (planeindex >= r_waterstate.numwaterplanes)
8706 // store the new plane
8707 r_waterstate.numwaterplanes++;
8709 // clear materialflags and pvs
8710 p->materialflags = 0;
8711 p->pvsvalid = false;
8712 p->camera_entity = t->camera_entity;
8713 VectorCopy(surface->mins, p->mins);
8714 VectorCopy(surface->maxs, p->maxs);
8719 p->mins[0] = min(p->mins[0], surface->mins[0]);
8720 p->mins[1] = min(p->mins[1], surface->mins[1]);
8721 p->mins[2] = min(p->mins[2], surface->mins[2]);
8722 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8723 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8724 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8726 // merge this surface's materialflags into the waterplane
8727 p->materialflags |= t->currentmaterialflags;
8728 if(!(p->materialflags & MATERIALFLAG_CAMERA))
8730 // merge this surface's PVS into the waterplane
8731 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8732 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8733 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8735 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8741 static void R_Water_ProcessPlanes(void)
8744 r_refdef_view_t originalview;
8745 r_refdef_view_t myview;
8747 r_waterstate_waterplane_t *p;
8750 originalview = r_refdef.view;
8752 // make sure enough textures are allocated
8753 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8755 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8757 if (!p->texture_refraction)
8758 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);
8759 if (!p->texture_refraction)
8762 else if (p->materialflags & MATERIALFLAG_CAMERA)
8764 if (!p->texture_camera)
8765 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);
8766 if (!p->texture_camera)
8770 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8772 if (!p->texture_reflection)
8773 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);
8774 if (!p->texture_reflection)
8780 r_refdef.view = originalview;
8781 r_refdef.view.showdebug = false;
8782 r_refdef.view.width = r_waterstate.waterwidth;
8783 r_refdef.view.height = r_waterstate.waterheight;
8784 r_refdef.view.useclipplane = true;
8785 myview = r_refdef.view;
8786 r_waterstate.renderingscene = true;
8787 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8789 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8791 r_refdef.view = myview;
8792 if(r_water_scissormode.integer)
8795 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8796 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8799 // render reflected scene and copy into texture
8800 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8801 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8802 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8803 r_refdef.view.clipplane = p->plane;
8805 // reverse the cullface settings for this render
8806 r_refdef.view.cullface_front = GL_FRONT;
8807 r_refdef.view.cullface_back = GL_BACK;
8808 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8810 r_refdef.view.usecustompvs = true;
8812 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8814 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8817 R_ResetViewRendering3D();
8818 R_ClearScreen(r_refdef.fogenabled);
8819 if(r_water_scissormode.integer & 2)
8820 R_View_UpdateWithScissor(myscissor);
8823 if(r_water_scissormode.integer & 1)
8824 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8827 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);
8830 // render the normal view scene and copy into texture
8831 // (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)
8832 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8834 r_refdef.view = myview;
8835 if(r_water_scissormode.integer)
8838 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8839 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8842 r_waterstate.renderingrefraction = true;
8844 r_refdef.view.clipplane = p->plane;
8845 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8846 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8848 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8850 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8851 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8852 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8853 R_RenderView_UpdateViewVectors();
8854 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8856 r_refdef.view.usecustompvs = true;
8857 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);
8861 PlaneClassify(&r_refdef.view.clipplane);
8863 R_ResetViewRendering3D();
8864 R_ClearScreen(r_refdef.fogenabled);
8865 if(r_water_scissormode.integer & 2)
8866 R_View_UpdateWithScissor(myscissor);
8869 if(r_water_scissormode.integer & 1)
8870 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8873 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);
8874 r_waterstate.renderingrefraction = false;
8876 else if (p->materialflags & MATERIALFLAG_CAMERA)
8878 r_refdef.view = myview;
8880 r_refdef.view.clipplane = p->plane;
8881 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8882 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8884 r_refdef.view.width = r_waterstate.camerawidth;
8885 r_refdef.view.height = r_waterstate.cameraheight;
8886 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8887 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8889 if(p->camera_entity)
8891 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8892 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8895 // note: all of the view is used for displaying... so
8896 // there is no use in scissoring
8898 // reverse the cullface settings for this render
8899 r_refdef.view.cullface_front = GL_FRONT;
8900 r_refdef.view.cullface_back = GL_BACK;
8901 // also reverse the view matrix
8902 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
8903 R_RenderView_UpdateViewVectors();
8904 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8906 r_refdef.view.usecustompvs = true;
8907 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);
8910 // camera needs no clipplane
8911 r_refdef.view.useclipplane = false;
8913 PlaneClassify(&r_refdef.view.clipplane);
8915 R_ResetViewRendering3D();
8916 R_ClearScreen(r_refdef.fogenabled);
8920 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);
8921 r_waterstate.renderingrefraction = false;
8925 r_waterstate.renderingscene = false;
8926 r_refdef.view = originalview;
8927 R_ResetViewRendering3D();
8928 R_ClearScreen(r_refdef.fogenabled);
8932 r_refdef.view = originalview;
8933 r_waterstate.renderingscene = false;
8934 Cvar_SetValueQuick(&r_water, 0);
8935 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
8939 void R_Bloom_StartFrame(void)
8941 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8943 switch(vid.renderpath)
8945 case RENDERPATH_GL20:
8946 case RENDERPATH_CGGL:
8947 case RENDERPATH_D3D9:
8948 case RENDERPATH_D3D10:
8949 case RENDERPATH_D3D11:
8951 case RENDERPATH_GL13:
8952 case RENDERPATH_GL11:
8956 // set bloomwidth and bloomheight to the bloom resolution that will be
8957 // used (often less than the screen resolution for faster rendering)
8958 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8959 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8960 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8961 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8962 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8964 // calculate desired texture sizes
8965 if (vid.support.arb_texture_non_power_of_two)
8967 screentexturewidth = r_refdef.view.width;
8968 screentextureheight = r_refdef.view.height;
8969 bloomtexturewidth = r_bloomstate.bloomwidth;
8970 bloomtextureheight = r_bloomstate.bloomheight;
8974 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
8975 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
8976 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
8977 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
8980 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))
8982 Cvar_SetValueQuick(&r_hdr, 0);
8983 Cvar_SetValueQuick(&r_bloom, 0);
8984 Cvar_SetValueQuick(&r_motionblur, 0);
8985 Cvar_SetValueQuick(&r_damageblur, 0);
8988 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)))
8989 screentexturewidth = screentextureheight = 0;
8990 if (!r_hdr.integer && !r_bloom.integer)
8991 bloomtexturewidth = bloomtextureheight = 0;
8993 // allocate textures as needed
8994 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8996 if (r_bloomstate.texture_screen)
8997 R_FreeTexture(r_bloomstate.texture_screen);
8998 r_bloomstate.texture_screen = NULL;
8999 r_bloomstate.screentexturewidth = screentexturewidth;
9000 r_bloomstate.screentextureheight = screentextureheight;
9001 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
9002 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);
9004 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
9006 if (r_bloomstate.texture_bloom)
9007 R_FreeTexture(r_bloomstate.texture_bloom);
9008 r_bloomstate.texture_bloom = NULL;
9009 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
9010 r_bloomstate.bloomtextureheight = bloomtextureheight;
9011 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
9012 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);
9015 // when doing a reduced render (HDR) we want to use a smaller area
9016 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
9017 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
9018 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
9019 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
9020 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
9022 // set up a texcoord array for the full resolution screen image
9023 // (we have to keep this around to copy back during final render)
9024 r_bloomstate.screentexcoord2f[0] = 0;
9025 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
9026 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
9027 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
9028 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
9029 r_bloomstate.screentexcoord2f[5] = 0;
9030 r_bloomstate.screentexcoord2f[6] = 0;
9031 r_bloomstate.screentexcoord2f[7] = 0;
9033 // set up a texcoord array for the reduced resolution bloom image
9034 // (which will be additive blended over the screen image)
9035 r_bloomstate.bloomtexcoord2f[0] = 0;
9036 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9037 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9038 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9039 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9040 r_bloomstate.bloomtexcoord2f[5] = 0;
9041 r_bloomstate.bloomtexcoord2f[6] = 0;
9042 r_bloomstate.bloomtexcoord2f[7] = 0;
9044 switch(vid.renderpath)
9046 case RENDERPATH_GL11:
9047 case RENDERPATH_GL13:
9048 case RENDERPATH_GL20:
9049 case RENDERPATH_CGGL:
9051 case RENDERPATH_D3D9:
9052 case RENDERPATH_D3D10:
9053 case RENDERPATH_D3D11:
9056 for (i = 0;i < 4;i++)
9058 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
9059 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
9060 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
9061 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
9067 if (r_hdr.integer || r_bloom.integer)
9069 r_bloomstate.enabled = true;
9070 r_bloomstate.hdr = r_hdr.integer != 0;
9073 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);
9076 void R_Bloom_CopyBloomTexture(float colorscale)
9078 r_refdef.stats.bloom++;
9080 // scale down screen texture to the bloom texture size
9082 R_SetViewport(&r_bloomstate.viewport);
9083 GL_BlendFunc(GL_ONE, GL_ZERO);
9084 GL_Color(colorscale, colorscale, colorscale, 1);
9085 // 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...
9086 switch(vid.renderpath)
9088 case RENDERPATH_GL11:
9089 case RENDERPATH_GL13:
9090 case RENDERPATH_GL20:
9091 case RENDERPATH_CGGL:
9092 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9094 case RENDERPATH_D3D9:
9095 case RENDERPATH_D3D10:
9096 case RENDERPATH_D3D11:
9097 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9100 // TODO: do boxfilter scale-down in shader?
9101 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9102 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9103 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9105 // we now have a bloom image in the framebuffer
9106 // copy it into the bloom image texture for later processing
9107 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);
9108 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9111 void R_Bloom_CopyHDRTexture(void)
9113 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);
9114 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9117 void R_Bloom_MakeTexture(void)
9120 float xoffset, yoffset, r, brighten;
9122 r_refdef.stats.bloom++;
9124 R_ResetViewRendering2D();
9126 // we have a bloom image in the framebuffer
9128 R_SetViewport(&r_bloomstate.viewport);
9130 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
9133 r = bound(0, r_bloom_colorexponent.value / x, 1);
9134 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9136 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
9137 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9138 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9139 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9141 // copy the vertically blurred bloom view to a texture
9142 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);
9143 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9146 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
9147 brighten = r_bloom_brighten.value;
9149 brighten *= r_hdr_range.value;
9150 brighten = sqrt(brighten);
9152 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
9153 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9155 for (dir = 0;dir < 2;dir++)
9157 // blend on at multiple vertical offsets to achieve a vertical blur
9158 // TODO: do offset blends using GLSL
9159 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
9160 GL_BlendFunc(GL_ONE, GL_ZERO);
9161 for (x = -range;x <= range;x++)
9163 if (!dir){xoffset = 0;yoffset = x;}
9164 else {xoffset = x;yoffset = 0;}
9165 xoffset /= (float)r_bloomstate.bloomtexturewidth;
9166 yoffset /= (float)r_bloomstate.bloomtextureheight;
9167 // compute a texcoord array with the specified x and y offset
9168 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
9169 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9170 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9171 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9172 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9173 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
9174 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
9175 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
9176 // this r value looks like a 'dot' particle, fading sharply to
9177 // black at the edges
9178 // (probably not realistic but looks good enough)
9179 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
9180 //r = brighten/(range*2+1);
9181 r = brighten / (range * 2 + 1);
9183 r *= (1 - x*x/(float)(range*range));
9184 GL_Color(r, r, r, 1);
9185 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
9186 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9187 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9188 GL_BlendFunc(GL_ONE, GL_ONE);
9191 // copy the vertically blurred bloom view to a texture
9192 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);
9193 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9197 void R_HDR_RenderBloomTexture(void)
9199 int oldwidth, oldheight;
9200 float oldcolorscale;
9203 oldwaterstate = r_waterstate.enabled;
9204 oldcolorscale = r_refdef.view.colorscale;
9205 oldwidth = r_refdef.view.width;
9206 oldheight = r_refdef.view.height;
9207 r_refdef.view.width = r_bloomstate.bloomwidth;
9208 r_refdef.view.height = r_bloomstate.bloomheight;
9210 if(r_hdr.integer < 2)
9211 r_waterstate.enabled = false;
9213 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
9214 // TODO: add exposure compensation features
9215 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
9217 r_refdef.view.showdebug = false;
9218 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
9220 R_ResetViewRendering3D();
9222 R_ClearScreen(r_refdef.fogenabled);
9223 if (r_timereport_active)
9224 R_TimeReport("HDRclear");
9227 if (r_timereport_active)
9228 R_TimeReport("visibility");
9230 // only do secondary renders with HDR if r_hdr is 2 or higher
9231 r_waterstate.numwaterplanes = 0;
9232 if (r_waterstate.enabled)
9233 R_RenderWaterPlanes();
9235 r_refdef.view.showdebug = true;
9237 r_waterstate.numwaterplanes = 0;
9239 R_ResetViewRendering2D();
9241 R_Bloom_CopyHDRTexture();
9242 R_Bloom_MakeTexture();
9244 // restore the view settings
9245 r_waterstate.enabled = oldwaterstate;
9246 r_refdef.view.width = oldwidth;
9247 r_refdef.view.height = oldheight;
9248 r_refdef.view.colorscale = oldcolorscale;
9250 R_ResetViewRendering3D();
9252 R_ClearScreen(r_refdef.fogenabled);
9253 if (r_timereport_active)
9254 R_TimeReport("viewclear");
9257 static void R_BlendView(void)
9259 unsigned int permutation;
9260 float uservecs[4][4];
9262 switch (vid.renderpath)
9264 case RENDERPATH_GL20:
9265 case RENDERPATH_CGGL:
9266 case RENDERPATH_D3D9:
9267 case RENDERPATH_D3D10:
9268 case RENDERPATH_D3D11:
9270 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
9271 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
9272 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
9273 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
9274 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
9276 if (r_bloomstate.texture_screen)
9278 // make sure the buffer is available
9279 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
9281 R_ResetViewRendering2D();
9283 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
9285 // declare variables
9287 static float avgspeed;
9289 speed = VectorLength(cl.movement_velocity);
9291 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
9292 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
9294 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
9295 speed = bound(0, speed, 1);
9296 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
9298 // calculate values into a standard alpha
9299 cl.motionbluralpha = 1 - exp(-
9301 (r_motionblur.value * speed / 80)
9303 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
9306 max(0.0001, cl.time - cl.oldtime) // fps independent
9309 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
9310 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
9312 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
9314 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9315 GL_Color(1, 1, 1, cl.motionbluralpha);
9316 switch(vid.renderpath)
9318 case RENDERPATH_GL11:
9319 case RENDERPATH_GL13:
9320 case RENDERPATH_GL20:
9321 case RENDERPATH_CGGL:
9322 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9324 case RENDERPATH_D3D9:
9325 case RENDERPATH_D3D10:
9326 case RENDERPATH_D3D11:
9327 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9330 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9331 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9332 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9336 // copy view into the screen texture
9337 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);
9338 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9340 else if (!r_bloomstate.texture_bloom)
9342 // we may still have to do view tint...
9343 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9345 // apply a color tint to the whole view
9346 R_ResetViewRendering2D();
9347 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9348 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9349 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9350 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9351 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9353 break; // no screen processing, no bloom, skip it
9356 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9358 // render simple bloom effect
9359 // copy the screen and shrink it and darken it for the bloom process
9360 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9361 // make the bloom texture
9362 R_Bloom_MakeTexture();
9365 #if _MSC_VER >= 1400
9366 #define sscanf sscanf_s
9368 memset(uservecs, 0, sizeof(uservecs));
9369 if (r_glsl_postprocess_uservec1_enable.integer)
9370 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9371 if (r_glsl_postprocess_uservec2_enable.integer)
9372 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9373 if (r_glsl_postprocess_uservec3_enable.integer)
9374 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9375 if (r_glsl_postprocess_uservec4_enable.integer)
9376 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9378 R_ResetViewRendering2D();
9379 GL_Color(1, 1, 1, 1);
9380 GL_BlendFunc(GL_ONE, GL_ZERO);
9382 switch(vid.renderpath)
9384 case RENDERPATH_GL20:
9385 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9386 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9387 if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
9388 if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
9389 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
9390 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]);
9391 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9392 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]);
9393 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]);
9394 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]);
9395 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]);
9396 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
9397 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9398 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);
9400 case RENDERPATH_CGGL:
9402 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9403 R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9404 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_bloomstate.texture_screen);CHECKCGERROR
9405 if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_bloomstate.texture_bloom );CHECKCGERROR
9406 if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps );CHECKCGERROR
9407 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
9408 if (r_cg_permutation->fp_PixelSize ) cgGLSetParameter2f( r_cg_permutation->fp_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9409 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
9410 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
9411 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
9412 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
9413 if (r_cg_permutation->fp_Saturation ) cgGLSetParameter1f( r_cg_permutation->fp_Saturation , r_glsl_saturation.value);CHECKCGERROR
9414 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9415 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);
9418 case RENDERPATH_D3D9:
9420 // 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...
9421 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9422 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9423 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
9424 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
9425 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
9426 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9427 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9428 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9429 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9430 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9431 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9432 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
9433 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9434 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9437 case RENDERPATH_D3D10:
9438 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9440 case RENDERPATH_D3D11:
9441 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9446 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9447 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9449 case RENDERPATH_GL13:
9450 case RENDERPATH_GL11:
9451 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9453 // apply a color tint to the whole view
9454 R_ResetViewRendering2D();
9455 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9456 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9457 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9458 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9459 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9465 matrix4x4_t r_waterscrollmatrix;
9467 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9469 if (r_refdef.fog_density)
9471 r_refdef.fogcolor[0] = r_refdef.fog_red;
9472 r_refdef.fogcolor[1] = r_refdef.fog_green;
9473 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9475 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9476 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9477 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9478 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9482 VectorCopy(r_refdef.fogcolor, fogvec);
9483 // color.rgb *= ContrastBoost * SceneBrightness;
9484 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9485 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9486 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9487 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9492 void R_UpdateVariables(void)
9496 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9498 r_refdef.farclip = r_farclip_base.value;
9499 if (r_refdef.scene.worldmodel)
9500 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9501 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9503 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9504 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9505 r_refdef.polygonfactor = 0;
9506 r_refdef.polygonoffset = 0;
9507 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9508 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9510 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9511 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9512 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
9513 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9514 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9515 if (FAKELIGHT_ENABLED)
9517 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
9519 if (r_showsurfaces.integer)
9521 r_refdef.scene.rtworld = false;
9522 r_refdef.scene.rtworldshadows = false;
9523 r_refdef.scene.rtdlight = false;
9524 r_refdef.scene.rtdlightshadows = false;
9525 r_refdef.lightmapintensity = 0;
9528 if (gamemode == GAME_NEHAHRA)
9530 if (gl_fogenable.integer)
9532 r_refdef.oldgl_fogenable = true;
9533 r_refdef.fog_density = gl_fogdensity.value;
9534 r_refdef.fog_red = gl_fogred.value;
9535 r_refdef.fog_green = gl_foggreen.value;
9536 r_refdef.fog_blue = gl_fogblue.value;
9537 r_refdef.fog_alpha = 1;
9538 r_refdef.fog_start = 0;
9539 r_refdef.fog_end = gl_skyclip.value;
9540 r_refdef.fog_height = 1<<30;
9541 r_refdef.fog_fadedepth = 128;
9543 else if (r_refdef.oldgl_fogenable)
9545 r_refdef.oldgl_fogenable = false;
9546 r_refdef.fog_density = 0;
9547 r_refdef.fog_red = 0;
9548 r_refdef.fog_green = 0;
9549 r_refdef.fog_blue = 0;
9550 r_refdef.fog_alpha = 0;
9551 r_refdef.fog_start = 0;
9552 r_refdef.fog_end = 0;
9553 r_refdef.fog_height = 1<<30;
9554 r_refdef.fog_fadedepth = 128;
9558 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9559 r_refdef.fog_start = max(0, r_refdef.fog_start);
9560 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9562 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9564 if (r_refdef.fog_density && r_drawfog.integer)
9566 r_refdef.fogenabled = true;
9567 // this is the point where the fog reaches 0.9986 alpha, which we
9568 // consider a good enough cutoff point for the texture
9569 // (0.9986 * 256 == 255.6)
9570 if (r_fog_exp2.integer)
9571 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9573 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9574 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9575 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9576 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9577 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9578 R_BuildFogHeightTexture();
9579 // fog color was already set
9580 // update the fog texture
9581 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)
9582 R_BuildFogTexture();
9583 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9584 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9587 r_refdef.fogenabled = false;
9589 switch(vid.renderpath)
9591 case RENDERPATH_GL20:
9592 case RENDERPATH_CGGL:
9593 case RENDERPATH_D3D9:
9594 case RENDERPATH_D3D10:
9595 case RENDERPATH_D3D11:
9596 if(v_glslgamma.integer && !vid_gammatables_trivial)
9598 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9600 // build GLSL gamma texture
9601 #define RAMPWIDTH 256
9602 unsigned short ramp[RAMPWIDTH * 3];
9603 unsigned char rampbgr[RAMPWIDTH][4];
9606 r_texture_gammaramps_serial = vid_gammatables_serial;
9608 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9609 for(i = 0; i < RAMPWIDTH; ++i)
9611 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9612 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9613 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9616 if (r_texture_gammaramps)
9618 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9622 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9628 // remove GLSL gamma texture
9631 case RENDERPATH_GL13:
9632 case RENDERPATH_GL11:
9637 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9638 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9644 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9645 if( scenetype != r_currentscenetype ) {
9646 // store the old scenetype
9647 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9648 r_currentscenetype = scenetype;
9649 // move in the new scene
9650 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9659 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9661 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9662 if( scenetype == r_currentscenetype ) {
9663 return &r_refdef.scene;
9665 return &r_scenes_store[ scenetype ];
9674 void R_RenderView(void)
9676 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
9677 if (r_timereport_active)
9678 R_TimeReport("start");
9679 r_textureframe++; // used only by R_GetCurrentTexture
9680 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9682 if(R_CompileShader_CheckStaticParms())
9685 if (!r_drawentities.integer)
9686 r_refdef.scene.numentities = 0;
9688 R_AnimCache_ClearCache();
9689 R_FrameData_NewFrame();
9691 /* adjust for stereo display */
9692 if(R_Stereo_Active())
9694 Matrix4x4_CreateFromQuakeEntity(&offsetmatrix, 0, r_stereo_separation.value * (0.5f - r_stereo_side), 0, 0, r_stereo_angle.value * (0.5f - r_stereo_side), 0, 1);
9695 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
9698 if (r_refdef.view.isoverlay)
9700 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9701 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9702 R_TimeReport("depthclear");
9704 r_refdef.view.showdebug = false;
9706 r_waterstate.enabled = false;
9707 r_waterstate.numwaterplanes = 0;
9711 r_refdef.view.matrix = originalmatrix;
9717 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9719 r_refdef.view.matrix = originalmatrix;
9720 return; //Host_Error ("R_RenderView: NULL worldmodel");
9723 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9725 R_RenderView_UpdateViewVectors();
9727 R_Shadow_UpdateWorldLightSelection();
9729 R_Bloom_StartFrame();
9730 R_Water_StartFrame();
9733 if (r_timereport_active)
9734 R_TimeReport("viewsetup");
9736 R_ResetViewRendering3D();
9738 if (r_refdef.view.clear || r_refdef.fogenabled)
9740 R_ClearScreen(r_refdef.fogenabled);
9741 if (r_timereport_active)
9742 R_TimeReport("viewclear");
9744 r_refdef.view.clear = true;
9746 // this produces a bloom texture to be used in R_BlendView() later
9747 if (r_hdr.integer && r_bloomstate.bloomwidth)
9749 R_HDR_RenderBloomTexture();
9750 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9751 r_textureframe++; // used only by R_GetCurrentTexture
9754 r_refdef.view.showdebug = true;
9757 if (r_timereport_active)
9758 R_TimeReport("visibility");
9760 r_waterstate.numwaterplanes = 0;
9761 if (r_waterstate.enabled)
9762 R_RenderWaterPlanes();
9765 r_waterstate.numwaterplanes = 0;
9768 if (r_timereport_active)
9769 R_TimeReport("blendview");
9771 GL_Scissor(0, 0, vid.width, vid.height);
9772 GL_ScissorTest(false);
9774 r_refdef.view.matrix = originalmatrix;
9779 void R_RenderWaterPlanes(void)
9781 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9783 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9784 if (r_timereport_active)
9785 R_TimeReport("waterworld");
9788 // don't let sound skip if going slow
9789 if (r_refdef.scene.extraupdate)
9792 R_DrawModelsAddWaterPlanes();
9793 if (r_timereport_active)
9794 R_TimeReport("watermodels");
9796 if (r_waterstate.numwaterplanes)
9798 R_Water_ProcessPlanes();
9799 if (r_timereport_active)
9800 R_TimeReport("waterscenes");
9804 extern void R_DrawLightningBeams (void);
9805 extern void VM_CL_AddPolygonsToMeshQueue (void);
9806 extern void R_DrawPortals (void);
9807 extern cvar_t cl_locs_show;
9808 static void R_DrawLocs(void);
9809 static void R_DrawEntityBBoxes(void);
9810 static void R_DrawModelDecals(void);
9811 extern void R_DrawModelShadows(void);
9812 extern void R_DrawModelShadowMaps(void);
9813 extern cvar_t cl_decals_newsystem;
9814 extern qboolean r_shadow_usingdeferredprepass;
9815 void R_RenderScene(void)
9817 qboolean shadowmapping = false;
9819 if (r_timereport_active)
9820 R_TimeReport("beginscene");
9822 r_refdef.stats.renders++;
9826 // don't let sound skip if going slow
9827 if (r_refdef.scene.extraupdate)
9830 R_MeshQueue_BeginScene();
9834 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);
9836 if (r_timereport_active)
9837 R_TimeReport("skystartframe");
9839 if (cl.csqc_vidvars.drawworld)
9841 // don't let sound skip if going slow
9842 if (r_refdef.scene.extraupdate)
9845 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9847 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9848 if (r_timereport_active)
9849 R_TimeReport("worldsky");
9852 if (R_DrawBrushModelsSky() && r_timereport_active)
9853 R_TimeReport("bmodelsky");
9855 if (skyrendermasked && skyrenderlater)
9857 // we have to force off the water clipping plane while rendering sky
9861 if (r_timereport_active)
9862 R_TimeReport("sky");
9866 R_AnimCache_CacheVisibleEntities();
9867 if (r_timereport_active)
9868 R_TimeReport("animation");
9870 R_Shadow_PrepareLights();
9871 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9872 R_Shadow_PrepareModelShadows();
9873 if (r_timereport_active)
9874 R_TimeReport("preparelights");
9876 if (R_Shadow_ShadowMappingEnabled())
9877 shadowmapping = true;
9879 if (r_shadow_usingdeferredprepass)
9880 R_Shadow_DrawPrepass();
9882 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9884 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9885 if (r_timereport_active)
9886 R_TimeReport("worlddepth");
9888 if (r_depthfirst.integer >= 2)
9890 R_DrawModelsDepth();
9891 if (r_timereport_active)
9892 R_TimeReport("modeldepth");
9895 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9897 R_DrawModelShadowMaps();
9898 R_ResetViewRendering3D();
9899 // don't let sound skip if going slow
9900 if (r_refdef.scene.extraupdate)
9904 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9906 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9907 if (r_timereport_active)
9908 R_TimeReport("world");
9911 // don't let sound skip if going slow
9912 if (r_refdef.scene.extraupdate)
9916 if (r_timereport_active)
9917 R_TimeReport("models");
9919 // don't let sound skip if going slow
9920 if (r_refdef.scene.extraupdate)
9923 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9925 R_DrawModelShadows();
9926 R_ResetViewRendering3D();
9927 // don't let sound skip if going slow
9928 if (r_refdef.scene.extraupdate)
9932 if (!r_shadow_usingdeferredprepass)
9934 R_Shadow_DrawLights();
9935 if (r_timereport_active)
9936 R_TimeReport("rtlights");
9939 // don't let sound skip if going slow
9940 if (r_refdef.scene.extraupdate)
9943 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9945 R_DrawModelShadows();
9946 R_ResetViewRendering3D();
9947 // don't let sound skip if going slow
9948 if (r_refdef.scene.extraupdate)
9952 if (cl.csqc_vidvars.drawworld)
9954 if (cl_decals_newsystem.integer)
9956 R_DrawModelDecals();
9957 if (r_timereport_active)
9958 R_TimeReport("modeldecals");
9963 if (r_timereport_active)
9964 R_TimeReport("decals");
9968 if (r_timereport_active)
9969 R_TimeReport("particles");
9972 if (r_timereport_active)
9973 R_TimeReport("explosions");
9975 R_DrawLightningBeams();
9976 if (r_timereport_active)
9977 R_TimeReport("lightning");
9980 VM_CL_AddPolygonsToMeshQueue();
9982 if (r_refdef.view.showdebug)
9984 if (cl_locs_show.integer)
9987 if (r_timereport_active)
9988 R_TimeReport("showlocs");
9991 if (r_drawportals.integer)
9994 if (r_timereport_active)
9995 R_TimeReport("portals");
9998 if (r_showbboxes.value > 0)
10000 R_DrawEntityBBoxes();
10001 if (r_timereport_active)
10002 R_TimeReport("bboxes");
10006 R_MeshQueue_RenderTransparent();
10007 if (r_timereport_active)
10008 R_TimeReport("drawtrans");
10010 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))
10012 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
10013 if (r_timereport_active)
10014 R_TimeReport("worlddebug");
10015 R_DrawModelsDebug();
10016 if (r_timereport_active)
10017 R_TimeReport("modeldebug");
10020 if (cl.csqc_vidvars.drawworld)
10022 R_Shadow_DrawCoronas();
10023 if (r_timereport_active)
10024 R_TimeReport("coronas");
10029 GL_DepthTest(false);
10030 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10031 GL_Color(1, 1, 1, 1);
10032 qglBegin(GL_POLYGON);
10033 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
10034 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
10035 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
10036 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
10038 qglBegin(GL_POLYGON);
10039 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]);
10040 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]);
10041 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]);
10042 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]);
10044 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10048 // don't let sound skip if going slow
10049 if (r_refdef.scene.extraupdate)
10052 R_ResetViewRendering2D();
10055 static const unsigned short bboxelements[36] =
10065 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
10068 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
10070 RSurf_ActiveWorldEntity();
10072 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10073 GL_DepthMask(false);
10074 GL_DepthRange(0, 1);
10075 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10076 // R_Mesh_ResetTextureState();
10078 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
10079 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
10080 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
10081 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
10082 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
10083 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
10084 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
10085 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
10086 R_FillColors(color4f, 8, cr, cg, cb, ca);
10087 if (r_refdef.fogenabled)
10089 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
10091 f1 = RSurf_FogVertex(v);
10093 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
10094 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
10095 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
10098 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
10099 R_Mesh_ResetTextureState();
10100 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10101 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
10104 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10108 prvm_edict_t *edict;
10109 prvm_prog_t *prog_save = prog;
10111 // this function draws bounding boxes of server entities
10115 GL_CullFace(GL_NONE);
10116 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10120 for (i = 0;i < numsurfaces;i++)
10122 edict = PRVM_EDICT_NUM(surfacelist[i]);
10123 switch ((int)edict->fields.server->solid)
10125 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
10126 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
10127 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
10128 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
10129 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
10130 default: Vector4Set(color, 0, 0, 0, 0.50);break;
10132 color[3] *= r_showbboxes.value;
10133 color[3] = bound(0, color[3], 1);
10134 GL_DepthTest(!r_showdisabledepthtest.integer);
10135 GL_CullFace(r_refdef.view.cullface_front);
10136 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
10142 static void R_DrawEntityBBoxes(void)
10145 prvm_edict_t *edict;
10147 prvm_prog_t *prog_save = prog;
10149 // this function draws bounding boxes of server entities
10155 for (i = 0;i < prog->num_edicts;i++)
10157 edict = PRVM_EDICT_NUM(i);
10158 if (edict->priv.server->free)
10160 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
10161 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
10163 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
10165 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
10166 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
10172 static const int nomodelelement3i[24] =
10184 static const unsigned short nomodelelement3s[24] =
10196 static const float nomodelvertex3f[6*3] =
10206 static const float nomodelcolor4f[6*4] =
10208 0.0f, 0.0f, 0.5f, 1.0f,
10209 0.0f, 0.0f, 0.5f, 1.0f,
10210 0.0f, 0.5f, 0.0f, 1.0f,
10211 0.0f, 0.5f, 0.0f, 1.0f,
10212 0.5f, 0.0f, 0.0f, 1.0f,
10213 0.5f, 0.0f, 0.0f, 1.0f
10216 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10220 float color4f[6*4];
10222 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);
10224 // this is only called once per entity so numsurfaces is always 1, and
10225 // surfacelist is always {0}, so this code does not handle batches
10227 if (rsurface.ent_flags & RENDER_ADDITIVE)
10229 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
10230 GL_DepthMask(false);
10232 else if (rsurface.colormod[3] < 1)
10234 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10235 GL_DepthMask(false);
10239 GL_BlendFunc(GL_ONE, GL_ZERO);
10240 GL_DepthMask(true);
10242 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
10243 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
10244 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
10245 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
10246 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
10247 for (i = 0, c = color4f;i < 6;i++, c += 4)
10249 c[0] *= rsurface.colormod[0];
10250 c[1] *= rsurface.colormod[1];
10251 c[2] *= rsurface.colormod[2];
10252 c[3] *= rsurface.colormod[3];
10254 if (r_refdef.fogenabled)
10256 for (i = 0, c = color4f;i < 6;i++, c += 4)
10258 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
10260 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
10261 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
10262 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
10265 // R_Mesh_ResetTextureState();
10266 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10267 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
10268 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
10271 void R_DrawNoModel(entity_render_t *ent)
10274 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
10275 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
10276 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
10278 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
10281 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
10283 vec3_t right1, right2, diff, normal;
10285 VectorSubtract (org2, org1, normal);
10287 // calculate 'right' vector for start
10288 VectorSubtract (r_refdef.view.origin, org1, diff);
10289 CrossProduct (normal, diff, right1);
10290 VectorNormalize (right1);
10292 // calculate 'right' vector for end
10293 VectorSubtract (r_refdef.view.origin, org2, diff);
10294 CrossProduct (normal, diff, right2);
10295 VectorNormalize (right2);
10297 vert[ 0] = org1[0] + width * right1[0];
10298 vert[ 1] = org1[1] + width * right1[1];
10299 vert[ 2] = org1[2] + width * right1[2];
10300 vert[ 3] = org1[0] - width * right1[0];
10301 vert[ 4] = org1[1] - width * right1[1];
10302 vert[ 5] = org1[2] - width * right1[2];
10303 vert[ 6] = org2[0] - width * right2[0];
10304 vert[ 7] = org2[1] - width * right2[1];
10305 vert[ 8] = org2[2] - width * right2[2];
10306 vert[ 9] = org2[0] + width * right2[0];
10307 vert[10] = org2[1] + width * right2[1];
10308 vert[11] = org2[2] + width * right2[2];
10311 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)
10313 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
10314 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
10315 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
10316 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
10317 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
10318 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
10319 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
10320 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
10321 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
10322 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
10323 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
10324 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
10327 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
10332 VectorSet(v, x, y, z);
10333 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
10334 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
10336 if (i == mesh->numvertices)
10338 if (mesh->numvertices < mesh->maxvertices)
10340 VectorCopy(v, vertex3f);
10341 mesh->numvertices++;
10343 return mesh->numvertices;
10349 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
10352 int *e, element[3];
10353 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10354 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10355 e = mesh->element3i + mesh->numtriangles * 3;
10356 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
10358 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
10359 if (mesh->numtriangles < mesh->maxtriangles)
10364 mesh->numtriangles++;
10366 element[1] = element[2];
10370 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
10373 int *e, element[3];
10374 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10375 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10376 e = mesh->element3i + mesh->numtriangles * 3;
10377 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10379 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10380 if (mesh->numtriangles < mesh->maxtriangles)
10385 mesh->numtriangles++;
10387 element[1] = element[2];
10391 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10392 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10394 int planenum, planenum2;
10397 mplane_t *plane, *plane2;
10399 double temppoints[2][256*3];
10400 // figure out how large a bounding box we need to properly compute this brush
10402 for (w = 0;w < numplanes;w++)
10403 maxdist = max(maxdist, fabs(planes[w].dist));
10404 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10405 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10406 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10410 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10411 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10413 if (planenum2 == planenum)
10415 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);
10418 if (tempnumpoints < 3)
10420 // generate elements forming a triangle fan for this polygon
10421 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10425 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)
10427 texturelayer_t *layer;
10428 layer = t->currentlayers + t->currentnumlayers++;
10429 layer->type = type;
10430 layer->depthmask = depthmask;
10431 layer->blendfunc1 = blendfunc1;
10432 layer->blendfunc2 = blendfunc2;
10433 layer->texture = texture;
10434 layer->texmatrix = *matrix;
10435 layer->color[0] = r;
10436 layer->color[1] = g;
10437 layer->color[2] = b;
10438 layer->color[3] = a;
10441 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10443 if(parms[0] == 0 && parms[1] == 0)
10445 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10446 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10451 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10454 index = parms[2] + r_refdef.scene.time * parms[3];
10455 index -= floor(index);
10456 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10459 case Q3WAVEFUNC_NONE:
10460 case Q3WAVEFUNC_NOISE:
10461 case Q3WAVEFUNC_COUNT:
10464 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10465 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10466 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10467 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10468 case Q3WAVEFUNC_TRIANGLE:
10470 f = index - floor(index);
10473 else if (index < 2)
10475 else if (index < 3)
10481 f = parms[0] + parms[1] * f;
10482 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10483 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10487 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10492 matrix4x4_t matrix, temp;
10493 switch(tcmod->tcmod)
10495 case Q3TCMOD_COUNT:
10497 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10498 matrix = r_waterscrollmatrix;
10500 matrix = identitymatrix;
10502 case Q3TCMOD_ENTITYTRANSLATE:
10503 // this is used in Q3 to allow the gamecode to control texcoord
10504 // scrolling on the entity, which is not supported in darkplaces yet.
10505 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10507 case Q3TCMOD_ROTATE:
10508 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10509 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10510 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10512 case Q3TCMOD_SCALE:
10513 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10515 case Q3TCMOD_SCROLL:
10516 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10518 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10519 w = (int) tcmod->parms[0];
10520 h = (int) tcmod->parms[1];
10521 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10523 idx = (int) floor(f * w * h);
10524 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10526 case Q3TCMOD_STRETCH:
10527 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10528 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10530 case Q3TCMOD_TRANSFORM:
10531 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
10532 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
10533 VectorSet(tcmat + 6, 0 , 0 , 1);
10534 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
10535 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10537 case Q3TCMOD_TURBULENT:
10538 // this is handled in the RSurf_PrepareVertices function
10539 matrix = identitymatrix;
10543 Matrix4x4_Concat(texmatrix, &matrix, &temp);
10546 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10548 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10549 char name[MAX_QPATH];
10550 skinframe_t *skinframe;
10551 unsigned char pixels[296*194];
10552 strlcpy(cache->name, skinname, sizeof(cache->name));
10553 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10554 if (developer_loading.integer)
10555 Con_Printf("loading %s\n", name);
10556 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10557 if (!skinframe || !skinframe->base)
10560 fs_offset_t filesize;
10562 f = FS_LoadFile(name, tempmempool, true, &filesize);
10565 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10566 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10570 cache->skinframe = skinframe;
10573 texture_t *R_GetCurrentTexture(texture_t *t)
10576 const entity_render_t *ent = rsurface.entity;
10577 dp_model_t *model = ent->model;
10578 q3shaderinfo_layer_tcmod_t *tcmod;
10580 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10581 return t->currentframe;
10582 t->update_lastrenderframe = r_textureframe;
10583 t->update_lastrenderentity = (void *)ent;
10585 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10586 t->camera_entity = ent->entitynumber;
10588 t->camera_entity = 0;
10590 // switch to an alternate material if this is a q1bsp animated material
10592 texture_t *texture = t;
10593 int s = rsurface.ent_skinnum;
10594 if ((unsigned int)s >= (unsigned int)model->numskins)
10596 if (model->skinscenes)
10598 if (model->skinscenes[s].framecount > 1)
10599 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10601 s = model->skinscenes[s].firstframe;
10604 t = t + s * model->num_surfaces;
10607 // use an alternate animation if the entity's frame is not 0,
10608 // and only if the texture has an alternate animation
10609 if (rsurface.ent_alttextures && t->anim_total[1])
10610 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10612 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10614 texture->currentframe = t;
10617 // update currentskinframe to be a qw skin or animation frame
10618 if (rsurface.ent_qwskin >= 0)
10620 i = rsurface.ent_qwskin;
10621 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10623 r_qwskincache_size = cl.maxclients;
10625 Mem_Free(r_qwskincache);
10626 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10628 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10629 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10630 t->currentskinframe = r_qwskincache[i].skinframe;
10631 if (t->currentskinframe == NULL)
10632 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10634 else if (t->numskinframes >= 2)
10635 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10636 if (t->backgroundnumskinframes >= 2)
10637 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10639 t->currentmaterialflags = t->basematerialflags;
10640 t->currentalpha = rsurface.colormod[3];
10641 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10642 t->currentalpha *= r_wateralpha.value;
10643 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10644 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10645 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10646 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10647 if (!(rsurface.ent_flags & RENDER_LIGHT))
10648 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10649 else if (FAKELIGHT_ENABLED)
10651 // no modellight if using fakelight for the map
10653 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10655 // pick a model lighting mode
10656 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10657 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10659 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10661 if (rsurface.ent_flags & RENDER_ADDITIVE)
10662 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10663 else if (t->currentalpha < 1)
10664 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10665 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10666 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10667 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10668 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10669 if (t->backgroundnumskinframes)
10670 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10671 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10673 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10674 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10677 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10678 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10679 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10681 // there is no tcmod
10682 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10684 t->currenttexmatrix = r_waterscrollmatrix;
10685 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10687 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10689 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10690 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10693 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10694 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10695 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10696 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10698 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10699 if (t->currentskinframe->qpixels)
10700 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10701 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10702 if (!t->basetexture)
10703 t->basetexture = r_texture_notexture;
10704 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10705 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10706 t->nmaptexture = t->currentskinframe->nmap;
10707 if (!t->nmaptexture)
10708 t->nmaptexture = r_texture_blanknormalmap;
10709 t->glosstexture = r_texture_black;
10710 t->glowtexture = t->currentskinframe->glow;
10711 t->fogtexture = t->currentskinframe->fog;
10712 t->reflectmasktexture = t->currentskinframe->reflect;
10713 if (t->backgroundnumskinframes)
10715 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10716 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10717 t->backgroundglosstexture = r_texture_black;
10718 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10719 if (!t->backgroundnmaptexture)
10720 t->backgroundnmaptexture = r_texture_blanknormalmap;
10724 t->backgroundbasetexture = r_texture_white;
10725 t->backgroundnmaptexture = r_texture_blanknormalmap;
10726 t->backgroundglosstexture = r_texture_black;
10727 t->backgroundglowtexture = NULL;
10729 t->specularpower = r_shadow_glossexponent.value;
10730 // TODO: store reference values for these in the texture?
10731 t->specularscale = 0;
10732 if (r_shadow_gloss.integer > 0)
10734 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10736 if (r_shadow_glossintensity.value > 0)
10738 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10739 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10740 t->specularscale = r_shadow_glossintensity.value;
10743 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10745 t->glosstexture = r_texture_white;
10746 t->backgroundglosstexture = r_texture_white;
10747 t->specularscale = r_shadow_gloss2intensity.value;
10748 t->specularpower = r_shadow_gloss2exponent.value;
10751 t->specularscale *= t->specularscalemod;
10752 t->specularpower *= t->specularpowermod;
10754 // lightmaps mode looks bad with dlights using actual texturing, so turn
10755 // off the colormap and glossmap, but leave the normalmap on as it still
10756 // accurately represents the shading involved
10757 if (gl_lightmaps.integer)
10759 t->basetexture = r_texture_grey128;
10760 t->pantstexture = r_texture_black;
10761 t->shirttexture = r_texture_black;
10762 t->nmaptexture = r_texture_blanknormalmap;
10763 t->glosstexture = r_texture_black;
10764 t->glowtexture = NULL;
10765 t->fogtexture = NULL;
10766 t->reflectmasktexture = NULL;
10767 t->backgroundbasetexture = NULL;
10768 t->backgroundnmaptexture = r_texture_blanknormalmap;
10769 t->backgroundglosstexture = r_texture_black;
10770 t->backgroundglowtexture = NULL;
10771 t->specularscale = 0;
10772 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10775 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10776 VectorClear(t->dlightcolor);
10777 t->currentnumlayers = 0;
10778 if (t->currentmaterialflags & MATERIALFLAG_WALL)
10780 int blendfunc1, blendfunc2;
10781 qboolean depthmask;
10782 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10784 blendfunc1 = GL_SRC_ALPHA;
10785 blendfunc2 = GL_ONE;
10787 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10789 blendfunc1 = GL_SRC_ALPHA;
10790 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10792 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10794 blendfunc1 = t->customblendfunc[0];
10795 blendfunc2 = t->customblendfunc[1];
10799 blendfunc1 = GL_ONE;
10800 blendfunc2 = GL_ZERO;
10802 // don't colormod evilblend textures
10803 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10804 VectorSet(t->lightmapcolor, 1, 1, 1);
10805 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10806 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10808 // fullbright is not affected by r_refdef.lightmapintensity
10809 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]);
10810 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10811 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]);
10812 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10813 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]);
10817 vec3_t ambientcolor;
10819 // set the color tint used for lights affecting this surface
10820 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10822 // q3bsp has no lightmap updates, so the lightstylevalue that
10823 // would normally be baked into the lightmap must be
10824 // applied to the color
10825 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10826 if (model->type == mod_brushq3)
10827 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10828 colorscale *= r_refdef.lightmapintensity;
10829 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10830 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10831 // basic lit geometry
10832 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]);
10833 // add pants/shirt if needed
10834 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10835 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]);
10836 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10837 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]);
10838 // now add ambient passes if needed
10839 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10841 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]);
10842 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10843 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]);
10844 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10845 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]);
10848 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10849 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]);
10850 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10852 // if this is opaque use alpha blend which will darken the earlier
10855 // if this is an alpha blended material, all the earlier passes
10856 // were darkened by fog already, so we only need to add the fog
10857 // color ontop through the fog mask texture
10859 // if this is an additive blended material, all the earlier passes
10860 // were darkened by fog already, and we should not add fog color
10861 // (because the background was not darkened, there is no fog color
10862 // that was lost behind it).
10863 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]);
10867 return t->currentframe;
10870 rsurfacestate_t rsurface;
10872 void RSurf_ActiveWorldEntity(void)
10874 dp_model_t *model = r_refdef.scene.worldmodel;
10875 //if (rsurface.entity == r_refdef.scene.worldentity)
10877 rsurface.entity = r_refdef.scene.worldentity;
10878 rsurface.skeleton = NULL;
10879 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10880 rsurface.ent_skinnum = 0;
10881 rsurface.ent_qwskin = -1;
10882 rsurface.ent_shadertime = 0;
10883 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10884 rsurface.matrix = identitymatrix;
10885 rsurface.inversematrix = identitymatrix;
10886 rsurface.matrixscale = 1;
10887 rsurface.inversematrixscale = 1;
10888 R_EntityMatrix(&identitymatrix);
10889 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10890 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10891 rsurface.fograngerecip = r_refdef.fograngerecip;
10892 rsurface.fogheightfade = r_refdef.fogheightfade;
10893 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10894 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10895 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10896 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10897 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10898 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10899 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10900 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10901 rsurface.colormod[3] = 1;
10902 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);
10903 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10904 rsurface.frameblend[0].lerp = 1;
10905 rsurface.ent_alttextures = false;
10906 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10907 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10908 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
10909 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10910 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10911 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10912 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10913 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10914 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10915 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10916 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10917 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
10918 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10919 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10920 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
10921 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10922 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10923 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
10924 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10925 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10926 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
10927 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10928 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10929 rsurface.modelelement3i = model->surfmesh.data_element3i;
10930 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10931 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10932 rsurface.modelelement3s = model->surfmesh.data_element3s;
10933 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10934 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10935 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10936 rsurface.modelnumvertices = model->surfmesh.num_vertices;
10937 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10938 rsurface.modelsurfaces = model->data_surfaces;
10939 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10940 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10941 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
10942 rsurface.modelgeneratedvertex = false;
10943 rsurface.batchgeneratedvertex = false;
10944 rsurface.batchfirstvertex = 0;
10945 rsurface.batchnumvertices = 0;
10946 rsurface.batchfirsttriangle = 0;
10947 rsurface.batchnumtriangles = 0;
10948 rsurface.batchvertex3f = NULL;
10949 rsurface.batchvertex3f_vertexbuffer = NULL;
10950 rsurface.batchvertex3f_bufferoffset = 0;
10951 rsurface.batchsvector3f = NULL;
10952 rsurface.batchsvector3f_vertexbuffer = NULL;
10953 rsurface.batchsvector3f_bufferoffset = 0;
10954 rsurface.batchtvector3f = NULL;
10955 rsurface.batchtvector3f_vertexbuffer = NULL;
10956 rsurface.batchtvector3f_bufferoffset = 0;
10957 rsurface.batchnormal3f = NULL;
10958 rsurface.batchnormal3f_vertexbuffer = NULL;
10959 rsurface.batchnormal3f_bufferoffset = 0;
10960 rsurface.batchlightmapcolor4f = NULL;
10961 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10962 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10963 rsurface.batchtexcoordtexture2f = NULL;
10964 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10965 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10966 rsurface.batchtexcoordlightmap2f = NULL;
10967 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10968 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10969 rsurface.batchvertexmesh = NULL;
10970 rsurface.batchvertexmeshbuffer = NULL;
10971 rsurface.batchvertex3fbuffer = NULL;
10972 rsurface.batchelement3i = NULL;
10973 rsurface.batchelement3i_indexbuffer = NULL;
10974 rsurface.batchelement3i_bufferoffset = 0;
10975 rsurface.batchelement3s = NULL;
10976 rsurface.batchelement3s_indexbuffer = NULL;
10977 rsurface.batchelement3s_bufferoffset = 0;
10978 rsurface.passcolor4f = NULL;
10979 rsurface.passcolor4f_vertexbuffer = NULL;
10980 rsurface.passcolor4f_bufferoffset = 0;
10983 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10985 dp_model_t *model = ent->model;
10986 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10988 rsurface.entity = (entity_render_t *)ent;
10989 rsurface.skeleton = ent->skeleton;
10990 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10991 rsurface.ent_skinnum = ent->skinnum;
10992 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;
10993 rsurface.ent_shadertime = ent->shadertime;
10994 rsurface.ent_flags = ent->flags;
10995 rsurface.matrix = ent->matrix;
10996 rsurface.inversematrix = ent->inversematrix;
10997 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10998 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10999 R_EntityMatrix(&rsurface.matrix);
11000 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11001 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11002 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11003 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11004 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11005 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11006 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
11007 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
11008 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
11009 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
11010 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
11011 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
11012 rsurface.colormod[3] = ent->alpha;
11013 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
11014 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
11015 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
11016 rsurface.basepolygonfactor = r_refdef.polygonfactor;
11017 rsurface.basepolygonoffset = r_refdef.polygonoffset;
11018 if (ent->model->brush.submodel && !prepass)
11020 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
11021 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
11023 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
11025 if (ent->animcache_vertex3f)
11027 rsurface.modelvertex3f = ent->animcache_vertex3f;
11028 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
11029 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
11030 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
11031 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
11032 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
11033 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
11035 else if (wanttangents)
11037 rsurface.modelvertex3f = R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11038 rsurface.modelsvector3f = R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11039 rsurface.modeltvector3f = R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11040 rsurface.modelnormal3f = R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11041 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
11042 rsurface.modelvertexmesh = NULL;
11043 rsurface.modelvertexmeshbuffer = NULL;
11044 rsurface.modelvertex3fbuffer = NULL;
11046 else if (wantnormals)
11048 rsurface.modelvertex3f = R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11049 rsurface.modelsvector3f = NULL;
11050 rsurface.modeltvector3f = NULL;
11051 rsurface.modelnormal3f = R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11052 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
11053 rsurface.modelvertexmesh = NULL;
11054 rsurface.modelvertexmeshbuffer = NULL;
11055 rsurface.modelvertex3fbuffer = NULL;
11059 rsurface.modelvertex3f = R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11060 rsurface.modelsvector3f = NULL;
11061 rsurface.modeltvector3f = NULL;
11062 rsurface.modelnormal3f = NULL;
11063 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
11064 rsurface.modelvertexmesh = NULL;
11065 rsurface.modelvertexmeshbuffer = NULL;
11066 rsurface.modelvertex3fbuffer = NULL;
11068 rsurface.modelvertex3f_vertexbuffer = 0;
11069 rsurface.modelvertex3f_bufferoffset = 0;
11070 rsurface.modelsvector3f_vertexbuffer = 0;
11071 rsurface.modelsvector3f_bufferoffset = 0;
11072 rsurface.modeltvector3f_vertexbuffer = 0;
11073 rsurface.modeltvector3f_bufferoffset = 0;
11074 rsurface.modelnormal3f_vertexbuffer = 0;
11075 rsurface.modelnormal3f_bufferoffset = 0;
11076 rsurface.modelgeneratedvertex = true;
11080 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
11081 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11082 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
11083 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
11084 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11085 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
11086 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
11087 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11088 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
11089 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
11090 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11091 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
11092 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
11093 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
11094 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
11095 rsurface.modelgeneratedvertex = false;
11097 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
11098 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11099 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11100 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
11101 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11102 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11103 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
11104 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11105 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11106 rsurface.modelelement3i = model->surfmesh.data_element3i;
11107 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11108 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11109 rsurface.modelelement3s = model->surfmesh.data_element3s;
11110 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11111 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11112 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11113 rsurface.modelnumvertices = model->surfmesh.num_vertices;
11114 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11115 rsurface.modelsurfaces = model->data_surfaces;
11116 rsurface.batchgeneratedvertex = false;
11117 rsurface.batchfirstvertex = 0;
11118 rsurface.batchnumvertices = 0;
11119 rsurface.batchfirsttriangle = 0;
11120 rsurface.batchnumtriangles = 0;
11121 rsurface.batchvertex3f = NULL;
11122 rsurface.batchvertex3f_vertexbuffer = NULL;
11123 rsurface.batchvertex3f_bufferoffset = 0;
11124 rsurface.batchsvector3f = NULL;
11125 rsurface.batchsvector3f_vertexbuffer = NULL;
11126 rsurface.batchsvector3f_bufferoffset = 0;
11127 rsurface.batchtvector3f = NULL;
11128 rsurface.batchtvector3f_vertexbuffer = NULL;
11129 rsurface.batchtvector3f_bufferoffset = 0;
11130 rsurface.batchnormal3f = NULL;
11131 rsurface.batchnormal3f_vertexbuffer = NULL;
11132 rsurface.batchnormal3f_bufferoffset = 0;
11133 rsurface.batchlightmapcolor4f = NULL;
11134 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11135 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11136 rsurface.batchtexcoordtexture2f = NULL;
11137 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11138 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11139 rsurface.batchtexcoordlightmap2f = NULL;
11140 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11141 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11142 rsurface.batchvertexmesh = NULL;
11143 rsurface.batchvertexmeshbuffer = NULL;
11144 rsurface.batchvertex3fbuffer = NULL;
11145 rsurface.batchelement3i = NULL;
11146 rsurface.batchelement3i_indexbuffer = NULL;
11147 rsurface.batchelement3i_bufferoffset = 0;
11148 rsurface.batchelement3s = NULL;
11149 rsurface.batchelement3s_indexbuffer = NULL;
11150 rsurface.batchelement3s_bufferoffset = 0;
11151 rsurface.passcolor4f = NULL;
11152 rsurface.passcolor4f_vertexbuffer = NULL;
11153 rsurface.passcolor4f_bufferoffset = 0;
11156 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)
11158 rsurface.entity = r_refdef.scene.worldentity;
11159 rsurface.skeleton = NULL;
11160 rsurface.ent_skinnum = 0;
11161 rsurface.ent_qwskin = -1;
11162 rsurface.ent_shadertime = shadertime;
11163 rsurface.ent_flags = entflags;
11164 rsurface.modelnumvertices = numvertices;
11165 rsurface.modelnumtriangles = numtriangles;
11166 rsurface.matrix = *matrix;
11167 rsurface.inversematrix = *inversematrix;
11168 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11169 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11170 R_EntityMatrix(&rsurface.matrix);
11171 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11172 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11173 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11174 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11175 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11176 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11177 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11178 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11179 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11180 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11181 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11182 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
11183 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);
11184 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11185 rsurface.frameblend[0].lerp = 1;
11186 rsurface.ent_alttextures = false;
11187 rsurface.basepolygonfactor = r_refdef.polygonfactor;
11188 rsurface.basepolygonoffset = r_refdef.polygonoffset;
11191 rsurface.modelvertex3f = (float *)vertex3f;
11192 rsurface.modelsvector3f = svector3f ? (float *)svector3f : R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11193 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11194 rsurface.modelnormal3f = normal3f ? (float *)normal3f : R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11196 else if (wantnormals)
11198 rsurface.modelvertex3f = (float *)vertex3f;
11199 rsurface.modelsvector3f = NULL;
11200 rsurface.modeltvector3f = NULL;
11201 rsurface.modelnormal3f = normal3f ? (float *)normal3f : R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11205 rsurface.modelvertex3f = (float *)vertex3f;
11206 rsurface.modelsvector3f = NULL;
11207 rsurface.modeltvector3f = NULL;
11208 rsurface.modelnormal3f = NULL;
11210 rsurface.modelvertexmesh = NULL;
11211 rsurface.modelvertexmeshbuffer = NULL;
11212 rsurface.modelvertex3fbuffer = NULL;
11213 rsurface.modelvertex3f_vertexbuffer = 0;
11214 rsurface.modelvertex3f_bufferoffset = 0;
11215 rsurface.modelsvector3f_vertexbuffer = 0;
11216 rsurface.modelsvector3f_bufferoffset = 0;
11217 rsurface.modeltvector3f_vertexbuffer = 0;
11218 rsurface.modeltvector3f_bufferoffset = 0;
11219 rsurface.modelnormal3f_vertexbuffer = 0;
11220 rsurface.modelnormal3f_bufferoffset = 0;
11221 rsurface.modelgeneratedvertex = true;
11222 rsurface.modellightmapcolor4f = (float *)color4f;
11223 rsurface.modellightmapcolor4f_vertexbuffer = 0;
11224 rsurface.modellightmapcolor4f_bufferoffset = 0;
11225 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
11226 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
11227 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
11228 rsurface.modeltexcoordlightmap2f = NULL;
11229 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
11230 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
11231 rsurface.modelelement3i = (int *)element3i;
11232 rsurface.modelelement3i_indexbuffer = NULL;
11233 rsurface.modelelement3i_bufferoffset = 0;
11234 rsurface.modelelement3s = (unsigned short *)element3s;
11235 rsurface.modelelement3s_indexbuffer = NULL;
11236 rsurface.modelelement3s_bufferoffset = 0;
11237 rsurface.modellightmapoffsets = NULL;
11238 rsurface.modelsurfaces = NULL;
11239 rsurface.batchgeneratedvertex = false;
11240 rsurface.batchfirstvertex = 0;
11241 rsurface.batchnumvertices = 0;
11242 rsurface.batchfirsttriangle = 0;
11243 rsurface.batchnumtriangles = 0;
11244 rsurface.batchvertex3f = NULL;
11245 rsurface.batchvertex3f_vertexbuffer = NULL;
11246 rsurface.batchvertex3f_bufferoffset = 0;
11247 rsurface.batchsvector3f = NULL;
11248 rsurface.batchsvector3f_vertexbuffer = NULL;
11249 rsurface.batchsvector3f_bufferoffset = 0;
11250 rsurface.batchtvector3f = NULL;
11251 rsurface.batchtvector3f_vertexbuffer = NULL;
11252 rsurface.batchtvector3f_bufferoffset = 0;
11253 rsurface.batchnormal3f = NULL;
11254 rsurface.batchnormal3f_vertexbuffer = NULL;
11255 rsurface.batchnormal3f_bufferoffset = 0;
11256 rsurface.batchlightmapcolor4f = NULL;
11257 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11258 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11259 rsurface.batchtexcoordtexture2f = NULL;
11260 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11261 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11262 rsurface.batchtexcoordlightmap2f = NULL;
11263 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11264 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11265 rsurface.batchvertexmesh = NULL;
11266 rsurface.batchvertexmeshbuffer = NULL;
11267 rsurface.batchvertex3fbuffer = NULL;
11268 rsurface.batchelement3i = NULL;
11269 rsurface.batchelement3i_indexbuffer = NULL;
11270 rsurface.batchelement3i_bufferoffset = 0;
11271 rsurface.batchelement3s = NULL;
11272 rsurface.batchelement3s_indexbuffer = NULL;
11273 rsurface.batchelement3s_bufferoffset = 0;
11274 rsurface.passcolor4f = NULL;
11275 rsurface.passcolor4f_vertexbuffer = NULL;
11276 rsurface.passcolor4f_bufferoffset = 0;
11278 if (rsurface.modelnumvertices && rsurface.modelelement3i)
11280 if ((wantnormals || wanttangents) && !normal3f)
11282 rsurface.modelnormal3f = R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11283 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
11285 if (wanttangents && !svector3f)
11287 rsurface.modelsvector3f = R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11288 rsurface.modeltvector3f = R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11289 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
11294 float RSurf_FogPoint(const float *v)
11296 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11297 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11298 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11299 float FogHeightFade = r_refdef.fogheightfade;
11301 unsigned int fogmasktableindex;
11302 if (r_refdef.fogplaneviewabove)
11303 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11305 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11306 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11307 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11310 float RSurf_FogVertex(const float *v)
11312 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11313 float FogPlaneViewDist = rsurface.fogplaneviewdist;
11314 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11315 float FogHeightFade = rsurface.fogheightfade;
11317 unsigned int fogmasktableindex;
11318 if (r_refdef.fogplaneviewabove)
11319 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11321 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11322 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11323 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11326 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11329 for (i = 0;i < numelements;i++)
11330 outelement3i[i] = inelement3i[i] + adjust;
11333 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11334 extern cvar_t gl_vbo;
11335 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11343 int surfacefirsttriangle;
11344 int surfacenumtriangles;
11345 int surfacefirstvertex;
11346 int surfaceendvertex;
11347 int surfacenumvertices;
11348 int batchnumvertices;
11349 int batchnumtriangles;
11353 qboolean dynamicvertex;
11357 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11358 float waveparms[4];
11359 q3shaderinfo_deform_t *deform;
11360 const msurface_t *surface, *firstsurface;
11361 r_vertexmesh_t *vertexmesh;
11362 if (!texturenumsurfaces)
11364 // find vertex range of this surface batch
11366 firstsurface = texturesurfacelist[0];
11367 firsttriangle = firstsurface->num_firsttriangle;
11368 batchnumvertices = 0;
11369 batchnumtriangles = 0;
11370 firstvertex = endvertex = firstsurface->num_firstvertex;
11371 for (i = 0;i < texturenumsurfaces;i++)
11373 surface = texturesurfacelist[i];
11374 if (surface != firstsurface + i)
11376 surfacefirstvertex = surface->num_firstvertex;
11377 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11378 surfacenumvertices = surface->num_vertices;
11379 surfacenumtriangles = surface->num_triangles;
11380 if (firstvertex > surfacefirstvertex)
11381 firstvertex = surfacefirstvertex;
11382 if (endvertex < surfaceendvertex)
11383 endvertex = surfaceendvertex;
11384 batchnumvertices += surfacenumvertices;
11385 batchnumtriangles += surfacenumtriangles;
11388 // we now know the vertex range used, and if there are any gaps in it
11389 rsurface.batchfirstvertex = firstvertex;
11390 rsurface.batchnumvertices = endvertex - firstvertex;
11391 rsurface.batchfirsttriangle = firsttriangle;
11392 rsurface.batchnumtriangles = batchnumtriangles;
11394 // this variable holds flags for which properties have been updated that
11395 // may require regenerating vertexmesh array...
11398 // check if any dynamic vertex processing must occur
11399 dynamicvertex = false;
11401 // if there is a chance of animated vertex colors, it's a dynamic batch
11402 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11404 dynamicvertex = true;
11405 batchneed |= BATCHNEED_NOGAPS;
11406 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
11409 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11411 switch (deform->deform)
11414 case Q3DEFORM_PROJECTIONSHADOW:
11415 case Q3DEFORM_TEXT0:
11416 case Q3DEFORM_TEXT1:
11417 case Q3DEFORM_TEXT2:
11418 case Q3DEFORM_TEXT3:
11419 case Q3DEFORM_TEXT4:
11420 case Q3DEFORM_TEXT5:
11421 case Q3DEFORM_TEXT6:
11422 case Q3DEFORM_TEXT7:
11423 case Q3DEFORM_NONE:
11425 case Q3DEFORM_AUTOSPRITE:
11426 dynamicvertex = true;
11427 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11428 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11430 case Q3DEFORM_AUTOSPRITE2:
11431 dynamicvertex = true;
11432 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11433 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11435 case Q3DEFORM_NORMAL:
11436 dynamicvertex = true;
11437 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11438 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11440 case Q3DEFORM_WAVE:
11441 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11442 break; // if wavefunc is a nop, ignore this transform
11443 dynamicvertex = true;
11444 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11445 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11447 case Q3DEFORM_BULGE:
11448 dynamicvertex = true;
11449 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11450 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11452 case Q3DEFORM_MOVE:
11453 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11454 break; // if wavefunc is a nop, ignore this transform
11455 dynamicvertex = true;
11456 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11457 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
11461 switch(rsurface.texture->tcgen.tcgen)
11464 case Q3TCGEN_TEXTURE:
11466 case Q3TCGEN_LIGHTMAP:
11467 dynamicvertex = true;
11468 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11469 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11471 case Q3TCGEN_VECTOR:
11472 dynamicvertex = true;
11473 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11474 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11476 case Q3TCGEN_ENVIRONMENT:
11477 dynamicvertex = true;
11478 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11479 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11482 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11484 dynamicvertex = true;
11485 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11486 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11489 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11491 dynamicvertex = true;
11492 batchneed |= BATCHNEED_NOGAPS;
11493 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11496 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11498 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11499 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
11500 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
11501 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
11502 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11503 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11504 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11507 // when the model data has no vertex buffer (dynamic mesh), we need to
11509 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
11510 batchneed |= BATCHNEED_NOGAPS;
11512 // if needsupdate, we have to do a dynamic vertex batch for sure
11513 if (needsupdate & batchneed)
11514 dynamicvertex = true;
11516 // see if we need to build vertexmesh from arrays
11517 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11518 dynamicvertex = true;
11520 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11521 // also some drivers strongly dislike firstvertex
11522 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11523 dynamicvertex = true;
11525 rsurface.batchvertex3f = rsurface.modelvertex3f;
11526 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11527 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11528 rsurface.batchsvector3f = rsurface.modelsvector3f;
11529 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11530 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11531 rsurface.batchtvector3f = rsurface.modeltvector3f;
11532 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11533 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11534 rsurface.batchnormal3f = rsurface.modelnormal3f;
11535 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11536 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11537 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11538 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
11539 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11540 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11541 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
11542 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
11543 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11544 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11545 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11546 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
11547 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11548 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11549 rsurface.batchelement3i = rsurface.modelelement3i;
11550 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11551 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11552 rsurface.batchelement3s = rsurface.modelelement3s;
11553 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11554 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11556 // if any dynamic vertex processing has to occur in software, we copy the
11557 // entire surface list together before processing to rebase the vertices
11558 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11560 // if any gaps exist and we do not have a static vertex buffer, we have to
11561 // copy the surface list together to avoid wasting upload bandwidth on the
11562 // vertices in the gaps.
11564 // if gaps exist and we have a static vertex buffer, we still have to
11565 // combine the index buffer ranges into one dynamic index buffer.
11567 // in all cases we end up with data that can be drawn in one call.
11569 if (!dynamicvertex)
11571 // static vertex data, just set pointers...
11572 rsurface.batchgeneratedvertex = false;
11573 // if there are gaps, we want to build a combined index buffer,
11574 // otherwise use the original static buffer with an appropriate offset
11577 // build a new triangle elements array for this batch
11578 rsurface.batchelement3i = R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11579 rsurface.batchfirsttriangle = 0;
11581 for (i = 0;i < texturenumsurfaces;i++)
11583 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11584 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11585 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11586 numtriangles += surfacenumtriangles;
11588 rsurface.batchelement3i_indexbuffer = NULL;
11589 rsurface.batchelement3i_bufferoffset = 0;
11590 rsurface.batchelement3s = NULL;
11591 rsurface.batchelement3s_indexbuffer = NULL;
11592 rsurface.batchelement3s_bufferoffset = 0;
11593 if (endvertex <= 65536)
11595 // make a 16bit (unsigned short) index array if possible
11596 rsurface.batchelement3s = R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11597 for (i = 0;i < numtriangles*3;i++)
11598 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11604 // something needs software processing, do it for real...
11605 // we only directly handle separate array data in this case and then
11606 // generate interleaved data if needed...
11607 rsurface.batchgeneratedvertex = true;
11609 // now copy the vertex data into a combined array and make an index array
11610 // (this is what Quake3 does all the time)
11611 //if (gaps || rsurface.batchfirstvertex)
11613 rsurface.batchvertex3fbuffer = NULL;
11614 rsurface.batchvertexmesh = NULL;
11615 rsurface.batchvertexmeshbuffer = NULL;
11616 rsurface.batchvertex3f = NULL;
11617 rsurface.batchvertex3f_vertexbuffer = NULL;
11618 rsurface.batchvertex3f_bufferoffset = 0;
11619 rsurface.batchsvector3f = NULL;
11620 rsurface.batchsvector3f_vertexbuffer = NULL;
11621 rsurface.batchsvector3f_bufferoffset = 0;
11622 rsurface.batchtvector3f = NULL;
11623 rsurface.batchtvector3f_vertexbuffer = NULL;
11624 rsurface.batchtvector3f_bufferoffset = 0;
11625 rsurface.batchnormal3f = NULL;
11626 rsurface.batchnormal3f_vertexbuffer = NULL;
11627 rsurface.batchnormal3f_bufferoffset = 0;
11628 rsurface.batchlightmapcolor4f = NULL;
11629 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11630 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11631 rsurface.batchtexcoordtexture2f = NULL;
11632 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11633 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11634 rsurface.batchtexcoordlightmap2f = NULL;
11635 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11636 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11637 rsurface.batchelement3i = R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11638 rsurface.batchelement3i_indexbuffer = NULL;
11639 rsurface.batchelement3i_bufferoffset = 0;
11640 rsurface.batchelement3s = NULL;
11641 rsurface.batchelement3s_indexbuffer = NULL;
11642 rsurface.batchelement3s_bufferoffset = 0;
11643 // we'll only be setting up certain arrays as needed
11644 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11645 rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
11646 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11647 rsurface.batchvertex3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11648 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11649 rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11650 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11652 rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11653 rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11655 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11656 rsurface.batchlightmapcolor4f = R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11657 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11658 rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11659 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11660 rsurface.batchtexcoordlightmap2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11663 for (i = 0;i < texturenumsurfaces;i++)
11665 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11666 surfacenumvertices = texturesurfacelist[i]->num_vertices;
11667 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11668 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11669 // copy only the data requested
11670 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11671 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11672 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11674 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11675 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11676 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11677 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11678 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11680 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11681 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11683 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11684 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11685 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11686 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11687 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11688 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11690 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11691 numvertices += surfacenumvertices;
11692 numtriangles += surfacenumtriangles;
11695 // generate a 16bit index array as well if possible
11696 // (in general, dynamic batches fit)
11697 if (numvertices <= 65536)
11699 rsurface.batchelement3s = R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11700 for (i = 0;i < numtriangles*3;i++)
11701 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11704 // since we've copied everything, the batch now starts at 0
11705 rsurface.batchfirstvertex = 0;
11706 rsurface.batchnumvertices = batchnumvertices;
11707 rsurface.batchfirsttriangle = 0;
11708 rsurface.batchnumtriangles = batchnumtriangles;
11711 // q1bsp surfaces rendered in vertex color mode have to have colors
11712 // calculated based on lightstyles
11713 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11715 // generate color arrays for the surfaces in this list
11719 const int *offsets;
11720 const unsigned char *lm;
11721 rsurface.batchlightmapcolor4f = R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11722 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11723 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11725 for (i = 0;i < texturenumsurfaces;i++)
11727 surface = texturesurfacelist[i];
11728 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11729 surfacenumvertices = surface->num_vertices;
11730 if (surface->lightmapinfo->samples)
11732 for (j = 0;j < surfacenumvertices;j++)
11734 lm = surface->lightmapinfo->samples + offsets[j];
11735 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11736 VectorScale(lm, scale, c);
11737 if (surface->lightmapinfo->styles[1] != 255)
11739 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11741 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11742 VectorMA(c, scale, lm, c);
11743 if (surface->lightmapinfo->styles[2] != 255)
11746 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11747 VectorMA(c, scale, lm, c);
11748 if (surface->lightmapinfo->styles[3] != 255)
11751 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11752 VectorMA(c, scale, lm, c);
11759 Vector4Set(rsurface.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);
11765 for (j = 0;j < surfacenumvertices;j++)
11767 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11774 // if vertices are deformed (sprite flares and things in maps, possibly
11775 // water waves, bulges and other deformations), modify the copied vertices
11777 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11779 switch (deform->deform)
11782 case Q3DEFORM_PROJECTIONSHADOW:
11783 case Q3DEFORM_TEXT0:
11784 case Q3DEFORM_TEXT1:
11785 case Q3DEFORM_TEXT2:
11786 case Q3DEFORM_TEXT3:
11787 case Q3DEFORM_TEXT4:
11788 case Q3DEFORM_TEXT5:
11789 case Q3DEFORM_TEXT6:
11790 case Q3DEFORM_TEXT7:
11791 case Q3DEFORM_NONE:
11793 case Q3DEFORM_AUTOSPRITE:
11794 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11795 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11796 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11797 VectorNormalize(newforward);
11798 VectorNormalize(newright);
11799 VectorNormalize(newup);
11800 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11801 // rsurface.batchvertex3f_vertexbuffer = NULL;
11802 // rsurface.batchvertex3f_bufferoffset = 0;
11803 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
11804 // rsurface.batchsvector3f_vertexbuffer = NULL;
11805 // rsurface.batchsvector3f_bufferoffset = 0;
11806 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
11807 // rsurface.batchtvector3f_vertexbuffer = NULL;
11808 // rsurface.batchtvector3f_bufferoffset = 0;
11809 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11810 // rsurface.batchnormal3f_vertexbuffer = NULL;
11811 // rsurface.batchnormal3f_bufferoffset = 0;
11812 // a single autosprite surface can contain multiple sprites...
11813 for (j = 0;j < batchnumvertices - 3;j += 4)
11815 VectorClear(center);
11816 for (i = 0;i < 4;i++)
11817 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11818 VectorScale(center, 0.25f, center);
11819 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11820 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11821 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11822 for (i = 0;i < 4;i++)
11824 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11825 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
11828 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11829 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11830 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
11832 case Q3DEFORM_AUTOSPRITE2:
11833 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11834 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11835 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11836 VectorNormalize(newforward);
11837 VectorNormalize(newright);
11838 VectorNormalize(newup);
11839 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11840 // rsurface.batchvertex3f_vertexbuffer = NULL;
11841 // rsurface.batchvertex3f_bufferoffset = 0;
11843 const float *v1, *v2;
11853 memset(shortest, 0, sizeof(shortest));
11854 // a single autosprite surface can contain multiple sprites...
11855 for (j = 0;j < batchnumvertices - 3;j += 4)
11857 VectorClear(center);
11858 for (i = 0;i < 4;i++)
11859 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11860 VectorScale(center, 0.25f, center);
11861 // find the two shortest edges, then use them to define the
11862 // axis vectors for rotating around the central axis
11863 for (i = 0;i < 6;i++)
11865 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11866 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11867 l = VectorDistance2(v1, v2);
11868 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11869 if (v1[2] != v2[2])
11870 l += (1.0f / 1024.0f);
11871 if (shortest[0].length2 > l || i == 0)
11873 shortest[1] = shortest[0];
11874 shortest[0].length2 = l;
11875 shortest[0].v1 = v1;
11876 shortest[0].v2 = v2;
11878 else if (shortest[1].length2 > l || i == 1)
11880 shortest[1].length2 = l;
11881 shortest[1].v1 = v1;
11882 shortest[1].v2 = v2;
11885 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11886 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11887 // this calculates the right vector from the shortest edge
11888 // and the up vector from the edge midpoints
11889 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11890 VectorNormalize(right);
11891 VectorSubtract(end, start, up);
11892 VectorNormalize(up);
11893 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11894 VectorSubtract(rsurface.localvieworigin, center, forward);
11895 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11896 VectorNegate(forward, forward);
11897 VectorReflect(forward, 0, up, forward);
11898 VectorNormalize(forward);
11899 CrossProduct(up, forward, newright);
11900 VectorNormalize(newright);
11901 // rotate the quad around the up axis vector, this is made
11902 // especially easy by the fact we know the quad is flat,
11903 // so we only have to subtract the center position and
11904 // measure distance along the right vector, and then
11905 // multiply that by the newright vector and add back the
11907 // we also need to subtract the old position to undo the
11908 // displacement from the center, which we do with a
11909 // DotProduct, the subtraction/addition of center is also
11910 // optimized into DotProducts here
11911 l = DotProduct(right, center);
11912 for (i = 0;i < 4;i++)
11914 v1 = rsurface.batchvertex3f + 3*(j+i);
11915 f = DotProduct(right, v1) - l;
11916 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
11920 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11922 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11923 // rsurface.batchnormal3f_vertexbuffer = NULL;
11924 // rsurface.batchnormal3f_bufferoffset = 0;
11925 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11927 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11929 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11930 // rsurface.batchsvector3f_vertexbuffer = NULL;
11931 // rsurface.batchsvector3f_bufferoffset = 0;
11932 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11933 // rsurface.batchtvector3f_vertexbuffer = NULL;
11934 // rsurface.batchtvector3f_bufferoffset = 0;
11935 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
11938 case Q3DEFORM_NORMAL:
11939 // deform the normals to make reflections wavey
11940 rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11941 rsurface.batchnormal3f_vertexbuffer = NULL;
11942 rsurface.batchnormal3f_bufferoffset = 0;
11943 for (j = 0;j < batchnumvertices;j++)
11946 float *normal = rsurface.batchnormal3f + 3*j;
11947 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11948 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11949 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]);
11950 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]);
11951 VectorNormalize(normal);
11953 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11955 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11956 // rsurface.batchsvector3f_vertexbuffer = NULL;
11957 // rsurface.batchsvector3f_bufferoffset = 0;
11958 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11959 // rsurface.batchtvector3f_vertexbuffer = NULL;
11960 // rsurface.batchtvector3f_bufferoffset = 0;
11961 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
11964 case Q3DEFORM_WAVE:
11965 // deform vertex array to make wavey water and flags and such
11966 waveparms[0] = deform->waveparms[0];
11967 waveparms[1] = deform->waveparms[1];
11968 waveparms[2] = deform->waveparms[2];
11969 waveparms[3] = deform->waveparms[3];
11970 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11971 break; // if wavefunc is a nop, don't make a dynamic vertex array
11972 // this is how a divisor of vertex influence on deformation
11973 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11974 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11975 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11976 // rsurface.batchvertex3f_vertexbuffer = NULL;
11977 // rsurface.batchvertex3f_bufferoffset = 0;
11978 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11979 // rsurface.batchnormal3f_vertexbuffer = NULL;
11980 // rsurface.batchnormal3f_bufferoffset = 0;
11981 for (j = 0;j < batchnumvertices;j++)
11983 // if the wavefunc depends on time, evaluate it per-vertex
11986 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11987 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11989 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
11991 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11992 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11993 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11995 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11996 // rsurface.batchsvector3f_vertexbuffer = NULL;
11997 // rsurface.batchsvector3f_bufferoffset = 0;
11998 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11999 // rsurface.batchtvector3f_vertexbuffer = NULL;
12000 // rsurface.batchtvector3f_bufferoffset = 0;
12001 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
12004 case Q3DEFORM_BULGE:
12005 // deform vertex array to make the surface have moving bulges
12006 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
12007 // rsurface.batchvertex3f_vertexbuffer = NULL;
12008 // rsurface.batchvertex3f_bufferoffset = 0;
12009 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
12010 // rsurface.batchnormal3f_vertexbuffer = NULL;
12011 // rsurface.batchnormal3f_bufferoffset = 0;
12012 for (j = 0;j < batchnumvertices;j++)
12014 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
12015 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
12017 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12018 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12019 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12021 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12022 // rsurface.batchsvector3f_vertexbuffer = NULL;
12023 // rsurface.batchsvector3f_bufferoffset = 0;
12024 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12025 // rsurface.batchtvector3f_vertexbuffer = NULL;
12026 // rsurface.batchtvector3f_bufferoffset = 0;
12027 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
12030 case Q3DEFORM_MOVE:
12031 // deform vertex array
12032 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
12033 break; // if wavefunc is a nop, don't make a dynamic vertex array
12034 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
12035 VectorScale(deform->parms, scale, waveparms);
12036 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
12037 // rsurface.batchvertex3f_vertexbuffer = NULL;
12038 // rsurface.batchvertex3f_bufferoffset = 0;
12039 for (j = 0;j < batchnumvertices;j++)
12040 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
12045 // generate texcoords based on the chosen texcoord source
12046 switch(rsurface.texture->tcgen.tcgen)
12049 case Q3TCGEN_TEXTURE:
12051 case Q3TCGEN_LIGHTMAP:
12052 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12053 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12054 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12055 if (rsurface.batchtexcoordlightmap2f)
12056 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
12058 case Q3TCGEN_VECTOR:
12059 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12060 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12061 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12062 for (j = 0;j < batchnumvertices;j++)
12064 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
12065 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
12068 case Q3TCGEN_ENVIRONMENT:
12069 // make environment reflections using a spheremap
12070 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12071 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12072 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12073 for (j = 0;j < batchnumvertices;j++)
12075 // identical to Q3A's method, but executed in worldspace so
12076 // carried models can be shiny too
12078 float viewer[3], d, reflected[3], worldreflected[3];
12080 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
12081 // VectorNormalize(viewer);
12083 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
12085 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
12086 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
12087 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
12088 // note: this is proportinal to viewer, so we can normalize later
12090 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
12091 VectorNormalize(worldreflected);
12093 // note: this sphere map only uses world x and z!
12094 // so positive and negative y will LOOK THE SAME.
12095 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
12096 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
12100 // the only tcmod that needs software vertex processing is turbulent, so
12101 // check for it here and apply the changes if needed
12102 // and we only support that as the first one
12103 // (handling a mixture of turbulent and other tcmods would be problematic
12104 // without punting it entirely to a software path)
12105 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
12107 amplitude = rsurface.texture->tcmods[0].parms[1];
12108 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
12109 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12110 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12111 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12112 for (j = 0;j < batchnumvertices;j++)
12114 rsurface.batchtexcoordtexture2f[j*2+0] += amplitude * sin(((rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12115 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12119 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
12121 // convert the modified arrays to vertex structs
12122 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
12123 // rsurface.batchvertexmeshbuffer = NULL;
12124 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
12125 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12126 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
12127 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
12128 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12129 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
12130 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
12132 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12134 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
12135 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
12138 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
12139 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12140 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
12141 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
12142 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12143 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
12144 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
12145 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12146 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
12150 void RSurf_DrawBatch(void)
12152 // sometimes a zero triangle surface (usually a degenerate patch) makes it
12153 // through the pipeline, killing it earlier in the pipeline would have
12154 // per-surface overhead rather than per-batch overhead, so it's best to
12155 // reject it here, before it hits glDraw.
12156 if (rsurface.batchnumtriangles == 0)
12159 // batch debugging code
12160 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
12166 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
12167 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
12170 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
12172 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
12174 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
12175 Sys_Error("RSurf_DrawBatch: index %i uses different texture (%s) than surface %i which it belongs to (which uses %s)\n", c, rsurface.texture->name, j, rsurface.modelsurfaces[j].texture->name);
12182 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);
12185 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
12187 // pick the closest matching water plane
12188 int planeindex, vertexindex, bestplaneindex = -1;
12192 r_waterstate_waterplane_t *p;
12193 qboolean prepared = false;
12195 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
12197 if(p->camera_entity != rsurface.texture->camera_entity)
12202 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12204 if(rsurface.batchnumvertices == 0)
12207 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
12209 Matrix4x4_Transform(&rsurface.matrix, v, vert);
12210 d += fabs(PlaneDiff(vert, &p->plane));
12212 if (bestd > d || bestplaneindex < 0)
12215 bestplaneindex = planeindex;
12218 return bestplaneindex;
12219 // NOTE: this MAY return a totally unrelated water plane; we can ignore
12220 // this situation though, as it might be better to render single larger
12221 // batches with useless stuff (backface culled for example) than to
12222 // render multiple smaller batches
12225 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
12228 rsurface.passcolor4f = R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12229 rsurface.passcolor4f_vertexbuffer = 0;
12230 rsurface.passcolor4f_bufferoffset = 0;
12231 for (i = 0;i < rsurface.batchnumvertices;i++)
12232 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
12235 static void RSurf_DrawBatch_GL11_ApplyFog(void)
12242 rsurface.passcolor4f = R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12243 rsurface.passcolor4f_vertexbuffer = 0;
12244 rsurface.passcolor4f_bufferoffset = 0;
12245 if (rsurface.passcolor4f)
12247 // generate color arrays
12248 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
12250 f = RSurf_FogVertex(v);
12259 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
12261 f = RSurf_FogVertex(v);
12270 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
12277 if (!rsurface.passcolor4f)
12279 rsurface.passcolor4f = R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12280 rsurface.passcolor4f_vertexbuffer = 0;
12281 rsurface.passcolor4f_bufferoffset = 0;
12282 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
12284 f = RSurf_FogVertex(v);
12285 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
12286 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
12287 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
12292 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
12297 if (!rsurface.passcolor4f)
12299 rsurface.passcolor4f = R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12300 rsurface.passcolor4f_vertexbuffer = 0;
12301 rsurface.passcolor4f_bufferoffset = 0;
12302 for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12311 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12316 if (!rsurface.passcolor4f)
12318 rsurface.passcolor4f = R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12319 rsurface.passcolor4f_vertexbuffer = 0;
12320 rsurface.passcolor4f_bufferoffset = 0;
12321 for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12323 c2[0] = c[0] + r_refdef.scene.ambient;
12324 c2[1] = c[1] + r_refdef.scene.ambient;
12325 c2[2] = c[2] + r_refdef.scene.ambient;
12330 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12333 rsurface.passcolor4f = NULL;
12334 rsurface.passcolor4f_vertexbuffer = 0;
12335 rsurface.passcolor4f_bufferoffset = 0;
12336 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12337 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12338 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12339 GL_Color(r, g, b, a);
12340 R_Mesh_TexBind(0, rsurface.lightmaptexture);
12344 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12346 // TODO: optimize applyfog && applycolor case
12347 // just apply fog if necessary, and tint the fog color array if necessary
12348 rsurface.passcolor4f = NULL;
12349 rsurface.passcolor4f_vertexbuffer = 0;
12350 rsurface.passcolor4f_bufferoffset = 0;
12351 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12352 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12353 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12354 GL_Color(r, g, b, a);
12358 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12361 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12362 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12363 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12364 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12365 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12366 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12367 GL_Color(r, g, b, a);
12371 static void RSurf_DrawBatch_GL11_ClampColor(void)
12376 if (!rsurface.passcolor4f)
12378 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12380 c2[0] = bound(0.0f, c1[0], 1.0f);
12381 c2[1] = bound(0.0f, c1[1], 1.0f);
12382 c2[2] = bound(0.0f, c1[2], 1.0f);
12383 c2[3] = bound(0.0f, c1[3], 1.0f);
12387 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
12397 rsurface.passcolor4f = R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12398 rsurface.passcolor4f_vertexbuffer = 0;
12399 rsurface.passcolor4f_bufferoffset = 0;
12400 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
12402 f = -DotProduct(r_refdef.view.forward, n);
12404 f = f * 0.85 + 0.15; // work around so stuff won't get black
12405 f *= r_refdef.lightmapintensity;
12406 Vector4Set(c, f, f, f, 1);
12410 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12412 RSurf_DrawBatch_GL11_ApplyFakeLight();
12413 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12414 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12415 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12416 GL_Color(r, g, b, a);
12420 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12428 vec3_t ambientcolor;
12429 vec3_t diffusecolor;
12433 VectorCopy(rsurface.modellight_lightdir, lightdir);
12434 f = 0.5f * r_refdef.lightmapintensity;
12435 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12436 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12437 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12438 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12439 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12440 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12442 if (VectorLength2(diffusecolor) > 0)
12444 // q3-style directional shading
12445 rsurface.passcolor4f = R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12446 rsurface.passcolor4f_vertexbuffer = 0;
12447 rsurface.passcolor4f_bufferoffset = 0;
12448 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
12450 if ((f = DotProduct(n, lightdir)) > 0)
12451 VectorMA(ambientcolor, f, diffusecolor, c);
12453 VectorCopy(ambientcolor, c);
12460 *applycolor = false;
12464 *r = ambientcolor[0];
12465 *g = ambientcolor[1];
12466 *b = ambientcolor[2];
12467 rsurface.passcolor4f = NULL;
12468 rsurface.passcolor4f_vertexbuffer = 0;
12469 rsurface.passcolor4f_bufferoffset = 0;
12473 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12475 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12476 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12477 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12478 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12479 GL_Color(r, g, b, a);
12483 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12489 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12491 f = 1 - RSurf_FogVertex(v);
12499 void RSurf_SetupDepthAndCulling(void)
12501 // submodels are biased to avoid z-fighting with world surfaces that they
12502 // may be exactly overlapping (avoids z-fighting artifacts on certain
12503 // doors and things in Quake maps)
12504 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12505 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12506 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12507 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12510 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12512 // transparent sky would be ridiculous
12513 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12515 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12516 skyrenderlater = true;
12517 RSurf_SetupDepthAndCulling();
12518 GL_DepthMask(true);
12519 // LordHavoc: HalfLife maps have freaky skypolys so don't use
12520 // skymasking on them, and Quake3 never did sky masking (unlike
12521 // software Quake and software Quake2), so disable the sky masking
12522 // in Quake3 maps as it causes problems with q3map2 sky tricks,
12523 // and skymasking also looks very bad when noclipping outside the
12524 // level, so don't use it then either.
12525 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12527 R_Mesh_ResetTextureState();
12528 if (skyrendermasked)
12530 R_SetupShader_DepthOrShadow();
12531 // depth-only (masking)
12532 GL_ColorMask(0,0,0,0);
12533 // just to make sure that braindead drivers don't draw
12534 // anything despite that colormask...
12535 GL_BlendFunc(GL_ZERO, GL_ONE);
12536 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12537 if (rsurface.batchvertex3fbuffer)
12538 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12540 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12544 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12546 GL_BlendFunc(GL_ONE, GL_ZERO);
12547 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12548 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12549 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12552 if (skyrendermasked)
12553 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12555 R_Mesh_ResetTextureState();
12556 GL_Color(1, 1, 1, 1);
12559 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12560 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12561 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12563 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12567 // render screenspace normalmap to texture
12568 GL_DepthMask(true);
12569 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12574 // bind lightmap texture
12576 // water/refraction/reflection/camera surfaces have to be handled specially
12577 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
12579 int start, end, startplaneindex;
12580 for (start = 0;start < texturenumsurfaces;start = end)
12582 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12583 if(startplaneindex < 0)
12585 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
12586 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
12590 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12592 // now that we have a batch using the same planeindex, render it
12593 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
12595 // render water or distortion background
12596 GL_DepthMask(true);
12597 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));
12599 // blend surface on top
12600 GL_DepthMask(false);
12601 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12604 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
12606 // render surface with reflection texture as input
12607 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12608 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));
12615 // render surface batch normally
12616 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12617 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12621 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12623 // OpenGL 1.3 path - anything not completely ancient
12624 qboolean applycolor;
12627 const texturelayer_t *layer;
12628 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);
12629 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12631 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12634 int layertexrgbscale;
12635 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12637 if (layerindex == 0)
12638 GL_AlphaTest(true);
12641 GL_AlphaTest(false);
12642 GL_DepthFunc(GL_EQUAL);
12645 GL_DepthMask(layer->depthmask && writedepth);
12646 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12647 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12649 layertexrgbscale = 4;
12650 VectorScale(layer->color, 0.25f, layercolor);
12652 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12654 layertexrgbscale = 2;
12655 VectorScale(layer->color, 0.5f, layercolor);
12659 layertexrgbscale = 1;
12660 VectorScale(layer->color, 1.0f, layercolor);
12662 layercolor[3] = layer->color[3];
12663 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12664 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12665 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12666 switch (layer->type)
12668 case TEXTURELAYERTYPE_LITTEXTURE:
12669 // single-pass lightmapped texture with 2x rgbscale
12670 R_Mesh_TexBind(0, r_texture_white);
12671 R_Mesh_TexMatrix(0, NULL);
12672 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12673 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12674 R_Mesh_TexBind(1, layer->texture);
12675 R_Mesh_TexMatrix(1, &layer->texmatrix);
12676 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12677 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12678 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12679 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12680 else if (FAKELIGHT_ENABLED)
12681 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12682 else if (rsurface.uselightmaptexture)
12683 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12685 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12687 case TEXTURELAYERTYPE_TEXTURE:
12688 // singletexture unlit texture with transparency support
12689 R_Mesh_TexBind(0, layer->texture);
12690 R_Mesh_TexMatrix(0, &layer->texmatrix);
12691 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12692 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12693 R_Mesh_TexBind(1, 0);
12694 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12695 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12697 case TEXTURELAYERTYPE_FOG:
12698 // singletexture fogging
12699 if (layer->texture)
12701 R_Mesh_TexBind(0, layer->texture);
12702 R_Mesh_TexMatrix(0, &layer->texmatrix);
12703 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12704 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12708 R_Mesh_TexBind(0, 0);
12709 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12711 R_Mesh_TexBind(1, 0);
12712 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12713 // generate a color array for the fog pass
12714 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12715 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12719 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12722 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12724 GL_DepthFunc(GL_LEQUAL);
12725 GL_AlphaTest(false);
12729 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12731 // OpenGL 1.1 - crusty old voodoo path
12734 const texturelayer_t *layer;
12735 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);
12736 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12738 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12740 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12742 if (layerindex == 0)
12743 GL_AlphaTest(true);
12746 GL_AlphaTest(false);
12747 GL_DepthFunc(GL_EQUAL);
12750 GL_DepthMask(layer->depthmask && writedepth);
12751 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12752 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12753 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12754 switch (layer->type)
12756 case TEXTURELAYERTYPE_LITTEXTURE:
12757 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12759 // two-pass lit texture with 2x rgbscale
12760 // first the lightmap pass
12761 R_Mesh_TexBind(0, r_texture_white);
12762 R_Mesh_TexMatrix(0, NULL);
12763 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12764 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12765 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12766 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12767 else if (FAKELIGHT_ENABLED)
12768 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12769 else if (rsurface.uselightmaptexture)
12770 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12772 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12773 // then apply the texture to it
12774 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12775 R_Mesh_TexBind(0, layer->texture);
12776 R_Mesh_TexMatrix(0, &layer->texmatrix);
12777 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12778 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12779 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);
12783 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12784 R_Mesh_TexBind(0, layer->texture);
12785 R_Mesh_TexMatrix(0, &layer->texmatrix);
12786 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12787 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12788 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12789 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);
12791 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);
12794 case TEXTURELAYERTYPE_TEXTURE:
12795 // singletexture unlit texture with transparency support
12796 R_Mesh_TexBind(0, layer->texture);
12797 R_Mesh_TexMatrix(0, &layer->texmatrix);
12798 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12799 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12800 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);
12802 case TEXTURELAYERTYPE_FOG:
12803 // singletexture fogging
12804 if (layer->texture)
12806 R_Mesh_TexBind(0, layer->texture);
12807 R_Mesh_TexMatrix(0, &layer->texmatrix);
12808 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12809 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12813 R_Mesh_TexBind(0, 0);
12814 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12816 // generate a color array for the fog pass
12817 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12818 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12822 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12825 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12827 GL_DepthFunc(GL_LEQUAL);
12828 GL_AlphaTest(false);
12832 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12836 r_vertexgeneric_t *batchvertex;
12839 GL_AlphaTest(false);
12840 // R_Mesh_ResetTextureState();
12841 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12843 if(rsurface.texture && rsurface.texture->currentskinframe)
12845 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12846 c[3] *= rsurface.texture->currentalpha;
12856 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12858 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12859 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12860 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12863 // brighten it up (as texture value 127 means "unlit")
12864 c[0] *= 2 * r_refdef.view.colorscale;
12865 c[1] *= 2 * r_refdef.view.colorscale;
12866 c[2] *= 2 * r_refdef.view.colorscale;
12868 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12869 c[3] *= r_wateralpha.value;
12871 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12873 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12874 GL_DepthMask(false);
12876 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12878 GL_BlendFunc(GL_ONE, GL_ONE);
12879 GL_DepthMask(false);
12881 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12883 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12884 GL_DepthMask(false);
12886 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12888 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12889 GL_DepthMask(false);
12893 GL_BlendFunc(GL_ONE, GL_ZERO);
12894 GL_DepthMask(writedepth);
12897 if (r_showsurfaces.integer == 3)
12899 rsurface.passcolor4f = NULL;
12901 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12903 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12905 rsurface.passcolor4f = NULL;
12906 rsurface.passcolor4f_vertexbuffer = 0;
12907 rsurface.passcolor4f_bufferoffset = 0;
12909 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12911 qboolean applycolor = true;
12914 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12916 r_refdef.lightmapintensity = 1;
12917 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12918 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12920 else if (FAKELIGHT_ENABLED)
12922 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12924 r_refdef.lightmapintensity = r_fakelight_intensity.value;
12925 RSurf_DrawBatch_GL11_ApplyFakeLight();
12926 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12930 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12932 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12933 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12934 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12937 if(!rsurface.passcolor4f)
12938 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12940 RSurf_DrawBatch_GL11_ApplyAmbient();
12941 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12942 if(r_refdef.fogenabled)
12943 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12944 RSurf_DrawBatch_GL11_ClampColor();
12946 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12947 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12950 else if (!r_refdef.view.showdebug)
12952 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12953 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12954 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12956 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12957 Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12959 R_Mesh_PrepareVertices_Generic_Unlock();
12962 else if (r_showsurfaces.integer == 4)
12964 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12965 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12966 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12968 unsigned char c = vi << 3;
12969 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12970 Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12972 R_Mesh_PrepareVertices_Generic_Unlock();
12975 else if (r_showsurfaces.integer == 2)
12978 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12979 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12980 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12982 unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12983 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12984 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12985 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12986 Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12987 Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12988 Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12990 R_Mesh_PrepareVertices_Generic_Unlock();
12991 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12995 int texturesurfaceindex;
12997 const msurface_t *surface;
12998 unsigned char surfacecolor4ub[4];
12999 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13000 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
13002 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
13004 surface = texturesurfacelist[texturesurfaceindex];
13005 k = (int)(((size_t)surface) / sizeof(msurface_t));
13006 Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
13007 for (j = 0;j < surface->num_vertices;j++)
13009 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13010 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
13014 R_Mesh_PrepareVertices_Generic_Unlock();
13019 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13022 RSurf_SetupDepthAndCulling();
13023 if (r_showsurfaces.integer)
13025 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13028 switch (vid.renderpath)
13030 case RENDERPATH_GL20:
13031 case RENDERPATH_CGGL:
13032 case RENDERPATH_D3D9:
13033 case RENDERPATH_D3D10:
13034 case RENDERPATH_D3D11:
13035 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13037 case RENDERPATH_GL13:
13038 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13040 case RENDERPATH_GL11:
13041 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13047 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13050 RSurf_SetupDepthAndCulling();
13051 if (r_showsurfaces.integer)
13053 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13056 switch (vid.renderpath)
13058 case RENDERPATH_GL20:
13059 case RENDERPATH_CGGL:
13060 case RENDERPATH_D3D9:
13061 case RENDERPATH_D3D10:
13062 case RENDERPATH_D3D11:
13063 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13065 case RENDERPATH_GL13:
13066 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13068 case RENDERPATH_GL11:
13069 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13075 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13078 int texturenumsurfaces, endsurface;
13079 texture_t *texture;
13080 const msurface_t *surface;
13081 #define MAXBATCH_TRANSPARENTSURFACES 256
13082 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
13084 // if the model is static it doesn't matter what value we give for
13085 // wantnormals and wanttangents, so this logic uses only rules applicable
13086 // to a model, knowing that they are meaningless otherwise
13087 if (ent == r_refdef.scene.worldentity)
13088 RSurf_ActiveWorldEntity();
13089 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13090 RSurf_ActiveModelEntity(ent, false, false, false);
13093 switch (vid.renderpath)
13095 case RENDERPATH_GL20:
13096 case RENDERPATH_CGGL:
13097 case RENDERPATH_D3D9:
13098 case RENDERPATH_D3D10:
13099 case RENDERPATH_D3D11:
13100 RSurf_ActiveModelEntity(ent, true, true, false);
13102 case RENDERPATH_GL13:
13103 case RENDERPATH_GL11:
13104 RSurf_ActiveModelEntity(ent, true, false, false);
13109 if (r_transparentdepthmasking.integer)
13111 qboolean setup = false;
13112 for (i = 0;i < numsurfaces;i = j)
13115 surface = rsurface.modelsurfaces + surfacelist[i];
13116 texture = surface->texture;
13117 rsurface.texture = R_GetCurrentTexture(texture);
13118 rsurface.lightmaptexture = NULL;
13119 rsurface.deluxemaptexture = NULL;
13120 rsurface.uselightmaptexture = false;
13121 // scan ahead until we find a different texture
13122 endsurface = min(i + 1024, numsurfaces);
13123 texturenumsurfaces = 0;
13124 texturesurfacelist[texturenumsurfaces++] = surface;
13125 for (;j < endsurface;j++)
13127 surface = rsurface.modelsurfaces + surfacelist[j];
13128 if (texture != surface->texture)
13130 texturesurfacelist[texturenumsurfaces++] = surface;
13132 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
13134 // render the range of surfaces as depth
13138 GL_ColorMask(0,0,0,0);
13140 GL_DepthTest(true);
13141 GL_BlendFunc(GL_ONE, GL_ZERO);
13142 GL_DepthMask(true);
13143 GL_AlphaTest(false);
13144 // R_Mesh_ResetTextureState();
13145 R_SetupShader_DepthOrShadow();
13147 RSurf_SetupDepthAndCulling();
13148 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
13149 if (rsurface.batchvertex3fbuffer)
13150 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
13152 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
13156 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
13159 for (i = 0;i < numsurfaces;i = j)
13162 surface = rsurface.modelsurfaces + surfacelist[i];
13163 texture = surface->texture;
13164 rsurface.texture = R_GetCurrentTexture(texture);
13165 // scan ahead until we find a different texture
13166 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
13167 texturenumsurfaces = 0;
13168 texturesurfacelist[texturenumsurfaces++] = surface;
13169 if(FAKELIGHT_ENABLED)
13171 rsurface.lightmaptexture = NULL;
13172 rsurface.deluxemaptexture = NULL;
13173 rsurface.uselightmaptexture = false;
13174 for (;j < endsurface;j++)
13176 surface = rsurface.modelsurfaces + surfacelist[j];
13177 if (texture != surface->texture)
13179 texturesurfacelist[texturenumsurfaces++] = surface;
13184 rsurface.lightmaptexture = surface->lightmaptexture;
13185 rsurface.deluxemaptexture = surface->deluxemaptexture;
13186 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
13187 for (;j < endsurface;j++)
13189 surface = rsurface.modelsurfaces + surfacelist[j];
13190 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
13192 texturesurfacelist[texturenumsurfaces++] = surface;
13195 // render the range of surfaces
13196 if (ent == r_refdef.scene.worldentity)
13197 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13199 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13201 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13202 GL_AlphaTest(false);
13205 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
13207 // transparent surfaces get pushed off into the transparent queue
13208 int surfacelistindex;
13209 const msurface_t *surface;
13210 vec3_t tempcenter, center;
13211 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
13213 surface = texturesurfacelist[surfacelistindex];
13214 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
13215 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
13216 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
13217 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
13218 if (queueentity->transparent_offset) // transparent offset
13220 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
13221 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
13222 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
13224 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
13228 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
13230 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
13232 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
13234 RSurf_SetupDepthAndCulling();
13235 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
13236 if (rsurface.batchvertex3fbuffer)
13237 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
13239 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
13243 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
13245 const entity_render_t *queueentity = r_refdef.scene.worldentity;
13248 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13251 if (!rsurface.texture->currentnumlayers)
13253 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13254 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13256 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13258 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13259 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13260 else if (!rsurface.texture->currentnumlayers)
13262 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13264 // in the deferred case, transparent surfaces were queued during prepass
13265 if (!r_shadow_usingdeferredprepass)
13266 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13270 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13271 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13276 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13279 texture_t *texture;
13280 R_FrameData_SetMark();
13281 // break the surface list down into batches by texture and use of lightmapping
13282 for (i = 0;i < numsurfaces;i = j)
13285 // texture is the base texture pointer, rsurface.texture is the
13286 // current frame/skin the texture is directing us to use (for example
13287 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13288 // use skin 1 instead)
13289 texture = surfacelist[i]->texture;
13290 rsurface.texture = R_GetCurrentTexture(texture);
13291 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13293 // if this texture is not the kind we want, skip ahead to the next one
13294 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13298 if(FAKELIGHT_ENABLED || depthonly || prepass)
13300 rsurface.lightmaptexture = NULL;
13301 rsurface.deluxemaptexture = NULL;
13302 rsurface.uselightmaptexture = false;
13303 // simply scan ahead until we find a different texture or lightmap state
13304 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13309 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13310 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13311 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13312 // simply scan ahead until we find a different texture or lightmap state
13313 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13316 // render the range of surfaces
13317 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
13319 R_FrameData_ReturnToMark();
13322 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
13326 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13329 if (!rsurface.texture->currentnumlayers)
13331 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13332 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13334 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13336 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13337 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13338 else if (!rsurface.texture->currentnumlayers)
13340 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13342 // in the deferred case, transparent surfaces were queued during prepass
13343 if (!r_shadow_usingdeferredprepass)
13344 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13348 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13349 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13354 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13357 texture_t *texture;
13358 R_FrameData_SetMark();
13359 // break the surface list down into batches by texture and use of lightmapping
13360 for (i = 0;i < numsurfaces;i = j)
13363 // texture is the base texture pointer, rsurface.texture is the
13364 // current frame/skin the texture is directing us to use (for example
13365 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13366 // use skin 1 instead)
13367 texture = surfacelist[i]->texture;
13368 rsurface.texture = R_GetCurrentTexture(texture);
13369 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13371 // if this texture is not the kind we want, skip ahead to the next one
13372 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13376 if(FAKELIGHT_ENABLED || depthonly || prepass)
13378 rsurface.lightmaptexture = NULL;
13379 rsurface.deluxemaptexture = NULL;
13380 rsurface.uselightmaptexture = false;
13381 // simply scan ahead until we find a different texture or lightmap state
13382 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13387 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13388 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13389 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13390 // simply scan ahead until we find a different texture or lightmap state
13391 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13394 // render the range of surfaces
13395 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
13397 R_FrameData_ReturnToMark();
13400 float locboxvertex3f[6*4*3] =
13402 1,0,1, 1,0,0, 1,1,0, 1,1,1,
13403 0,1,1, 0,1,0, 0,0,0, 0,0,1,
13404 1,1,1, 1,1,0, 0,1,0, 0,1,1,
13405 0,0,1, 0,0,0, 1,0,0, 1,0,1,
13406 0,0,1, 1,0,1, 1,1,1, 0,1,1,
13407 1,0,0, 0,0,0, 0,1,0, 1,1,0
13410 unsigned short locboxelements[6*2*3] =
13415 12,13,14, 12,14,15,
13416 16,17,18, 16,18,19,
13420 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13423 cl_locnode_t *loc = (cl_locnode_t *)ent;
13425 float vertex3f[6*4*3];
13427 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13428 GL_DepthMask(false);
13429 GL_DepthRange(0, 1);
13430 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13431 GL_DepthTest(true);
13432 GL_CullFace(GL_NONE);
13433 R_EntityMatrix(&identitymatrix);
13435 // R_Mesh_ResetTextureState();
13437 i = surfacelist[0];
13438 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13439 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13440 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13441 surfacelist[0] < 0 ? 0.5f : 0.125f);
13443 if (VectorCompare(loc->mins, loc->maxs))
13445 VectorSet(size, 2, 2, 2);
13446 VectorMA(loc->mins, -0.5f, size, mins);
13450 VectorCopy(loc->mins, mins);
13451 VectorSubtract(loc->maxs, loc->mins, size);
13454 for (i = 0;i < 6*4*3;)
13455 for (j = 0;j < 3;j++, i++)
13456 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13458 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13459 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13460 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13463 void R_DrawLocs(void)
13466 cl_locnode_t *loc, *nearestloc;
13468 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13469 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13471 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13472 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13476 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13478 if (decalsystem->decals)
13479 Mem_Free(decalsystem->decals);
13480 memset(decalsystem, 0, sizeof(*decalsystem));
13483 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)
13486 tridecal_t *decals;
13489 // expand or initialize the system
13490 if (decalsystem->maxdecals <= decalsystem->numdecals)
13492 decalsystem_t old = *decalsystem;
13493 qboolean useshortelements;
13494 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13495 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13496 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)));
13497 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13498 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13499 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13500 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13501 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13502 if (decalsystem->numdecals)
13503 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13505 Mem_Free(old.decals);
13506 for (i = 0;i < decalsystem->maxdecals*3;i++)
13507 decalsystem->element3i[i] = i;
13508 if (useshortelements)
13509 for (i = 0;i < decalsystem->maxdecals*3;i++)
13510 decalsystem->element3s[i] = i;
13513 // grab a decal and search for another free slot for the next one
13514 decals = decalsystem->decals;
13515 decal = decalsystem->decals + (i = decalsystem->freedecal++);
13516 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13518 decalsystem->freedecal = i;
13519 if (decalsystem->numdecals <= i)
13520 decalsystem->numdecals = i + 1;
13522 // initialize the decal
13524 decal->triangleindex = triangleindex;
13525 decal->surfaceindex = surfaceindex;
13526 decal->decalsequence = decalsequence;
13527 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13528 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13529 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13530 decal->color4ub[0][3] = 255;
13531 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13532 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13533 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13534 decal->color4ub[1][3] = 255;
13535 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13536 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13537 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13538 decal->color4ub[2][3] = 255;
13539 decal->vertex3f[0][0] = v0[0];
13540 decal->vertex3f[0][1] = v0[1];
13541 decal->vertex3f[0][2] = v0[2];
13542 decal->vertex3f[1][0] = v1[0];
13543 decal->vertex3f[1][1] = v1[1];
13544 decal->vertex3f[1][2] = v1[2];
13545 decal->vertex3f[2][0] = v2[0];
13546 decal->vertex3f[2][1] = v2[1];
13547 decal->vertex3f[2][2] = v2[2];
13548 decal->texcoord2f[0][0] = t0[0];
13549 decal->texcoord2f[0][1] = t0[1];
13550 decal->texcoord2f[1][0] = t1[0];
13551 decal->texcoord2f[1][1] = t1[1];
13552 decal->texcoord2f[2][0] = t2[0];
13553 decal->texcoord2f[2][1] = t2[1];
13556 extern cvar_t cl_decals_bias;
13557 extern cvar_t cl_decals_models;
13558 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13559 // baseparms, parms, temps
13560 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)
13565 const float *vertex3f;
13567 float points[2][9][3];
13574 e = rsurface.modelelement3i + 3*triangleindex;
13576 vertex3f = rsurface.modelvertex3f;
13578 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13580 index = 3*e[cornerindex];
13581 VectorCopy(vertex3f + index, v[cornerindex]);
13584 //TriangleNormal(v[0], v[1], v[2], normal);
13585 //if (DotProduct(normal, localnormal) < 0.0f)
13587 // clip by each of the box planes formed from the projection matrix
13588 // if anything survives, we emit the decal
13589 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]);
13592 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]);
13595 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]);
13598 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]);
13601 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]);
13604 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]);
13607 // some part of the triangle survived, so we have to accept it...
13610 // dynamic always uses the original triangle
13612 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13614 index = 3*e[cornerindex];
13615 VectorCopy(vertex3f + index, v[cornerindex]);
13618 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13620 // convert vertex positions to texcoords
13621 Matrix4x4_Transform(projection, v[cornerindex], temp);
13622 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13623 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13624 // calculate distance fade from the projection origin
13625 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13626 f = bound(0.0f, f, 1.0f);
13627 c[cornerindex][0] = r * f;
13628 c[cornerindex][1] = g * f;
13629 c[cornerindex][2] = b * f;
13630 c[cornerindex][3] = 1.0f;
13631 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13634 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);
13636 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13637 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);
13639 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)
13641 matrix4x4_t projection;
13642 decalsystem_t *decalsystem;
13645 const msurface_t *surface;
13646 const msurface_t *surfaces;
13647 const int *surfacelist;
13648 const texture_t *texture;
13650 int numsurfacelist;
13651 int surfacelistindex;
13654 float localorigin[3];
13655 float localnormal[3];
13656 float localmins[3];
13657 float localmaxs[3];
13660 float planes[6][4];
13663 int bih_triangles_count;
13664 int bih_triangles[256];
13665 int bih_surfaces[256];
13667 decalsystem = &ent->decalsystem;
13668 model = ent->model;
13669 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13671 R_DecalSystem_Reset(&ent->decalsystem);
13675 if (!model->brush.data_leafs && !cl_decals_models.integer)
13677 if (decalsystem->model)
13678 R_DecalSystem_Reset(decalsystem);
13682 if (decalsystem->model != model)
13683 R_DecalSystem_Reset(decalsystem);
13684 decalsystem->model = model;
13686 RSurf_ActiveModelEntity(ent, false, false, false);
13688 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13689 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13690 VectorNormalize(localnormal);
13691 localsize = worldsize*rsurface.inversematrixscale;
13692 localmins[0] = localorigin[0] - localsize;
13693 localmins[1] = localorigin[1] - localsize;
13694 localmins[2] = localorigin[2] - localsize;
13695 localmaxs[0] = localorigin[0] + localsize;
13696 localmaxs[1] = localorigin[1] + localsize;
13697 localmaxs[2] = localorigin[2] + localsize;
13699 //VectorCopy(localnormal, planes[4]);
13700 //VectorVectors(planes[4], planes[2], planes[0]);
13701 AnglesFromVectors(angles, localnormal, NULL, false);
13702 AngleVectors(angles, planes[0], planes[2], planes[4]);
13703 VectorNegate(planes[0], planes[1]);
13704 VectorNegate(planes[2], planes[3]);
13705 VectorNegate(planes[4], planes[5]);
13706 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13707 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13708 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13709 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13710 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13711 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13716 matrix4x4_t forwardprojection;
13717 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13718 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13723 float projectionvector[4][3];
13724 VectorScale(planes[0], ilocalsize, projectionvector[0]);
13725 VectorScale(planes[2], ilocalsize, projectionvector[1]);
13726 VectorScale(planes[4], ilocalsize, projectionvector[2]);
13727 projectionvector[0][0] = planes[0][0] * ilocalsize;
13728 projectionvector[0][1] = planes[1][0] * ilocalsize;
13729 projectionvector[0][2] = planes[2][0] * ilocalsize;
13730 projectionvector[1][0] = planes[0][1] * ilocalsize;
13731 projectionvector[1][1] = planes[1][1] * ilocalsize;
13732 projectionvector[1][2] = planes[2][1] * ilocalsize;
13733 projectionvector[2][0] = planes[0][2] * ilocalsize;
13734 projectionvector[2][1] = planes[1][2] * ilocalsize;
13735 projectionvector[2][2] = planes[2][2] * ilocalsize;
13736 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13737 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13738 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13739 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13743 dynamic = model->surfmesh.isanimated;
13744 numsurfacelist = model->nummodelsurfaces;
13745 surfacelist = model->sortedmodelsurfaces;
13746 surfaces = model->data_surfaces;
13749 bih_triangles_count = -1;
13752 if(model->render_bih.numleafs)
13753 bih = &model->render_bih;
13754 else if(model->collision_bih.numleafs)
13755 bih = &model->collision_bih;
13758 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13759 if(bih_triangles_count == 0)
13761 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13763 if(bih_triangles_count > 0)
13765 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13767 surfaceindex = bih_surfaces[triangleindex];
13768 surface = surfaces + surfaceindex;
13769 texture = surface->texture;
13770 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13772 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13774 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13779 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13781 surfaceindex = surfacelist[surfacelistindex];
13782 surface = surfaces + surfaceindex;
13783 // check cull box first because it rejects more than any other check
13784 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13786 // skip transparent surfaces
13787 texture = surface->texture;
13788 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13790 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13792 numtriangles = surface->num_triangles;
13793 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13794 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13799 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13800 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)
13802 int renderentityindex;
13803 float worldmins[3];
13804 float worldmaxs[3];
13805 entity_render_t *ent;
13807 if (!cl_decals_newsystem.integer)
13810 worldmins[0] = worldorigin[0] - worldsize;
13811 worldmins[1] = worldorigin[1] - worldsize;
13812 worldmins[2] = worldorigin[2] - worldsize;
13813 worldmaxs[0] = worldorigin[0] + worldsize;
13814 worldmaxs[1] = worldorigin[1] + worldsize;
13815 worldmaxs[2] = worldorigin[2] + worldsize;
13817 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13819 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13821 ent = r_refdef.scene.entities[renderentityindex];
13822 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13825 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13829 typedef struct r_decalsystem_splatqueue_s
13831 vec3_t worldorigin;
13832 vec3_t worldnormal;
13838 r_decalsystem_splatqueue_t;
13840 int r_decalsystem_numqueued = 0;
13841 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13843 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)
13845 r_decalsystem_splatqueue_t *queue;
13847 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13850 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13851 VectorCopy(worldorigin, queue->worldorigin);
13852 VectorCopy(worldnormal, queue->worldnormal);
13853 Vector4Set(queue->color, r, g, b, a);
13854 Vector4Set(queue->tcrange, s1, t1, s2, t2);
13855 queue->worldsize = worldsize;
13856 queue->decalsequence = cl.decalsequence++;
13859 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13862 r_decalsystem_splatqueue_t *queue;
13864 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13865 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);
13866 r_decalsystem_numqueued = 0;
13869 extern cvar_t cl_decals_max;
13870 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13873 decalsystem_t *decalsystem = &ent->decalsystem;
13880 if (!decalsystem->numdecals)
13883 if (r_showsurfaces.integer)
13886 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13888 R_DecalSystem_Reset(decalsystem);
13892 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13893 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13895 if (decalsystem->lastupdatetime)
13896 frametime = (cl.time - decalsystem->lastupdatetime);
13899 decalsystem->lastupdatetime = cl.time;
13900 decal = decalsystem->decals;
13901 numdecals = decalsystem->numdecals;
13903 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13905 if (decal->color4ub[0][3])
13907 decal->lived += frametime;
13908 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13910 memset(decal, 0, sizeof(*decal));
13911 if (decalsystem->freedecal > i)
13912 decalsystem->freedecal = i;
13916 decal = decalsystem->decals;
13917 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13920 // collapse the array by shuffling the tail decals into the gaps
13923 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13924 decalsystem->freedecal++;
13925 if (decalsystem->freedecal == numdecals)
13927 decal[decalsystem->freedecal] = decal[--numdecals];
13930 decalsystem->numdecals = numdecals;
13932 if (numdecals <= 0)
13934 // if there are no decals left, reset decalsystem
13935 R_DecalSystem_Reset(decalsystem);
13939 extern skinframe_t *decalskinframe;
13940 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13943 decalsystem_t *decalsystem = &ent->decalsystem;
13952 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13955 numdecals = decalsystem->numdecals;
13959 if (r_showsurfaces.integer)
13962 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13964 R_DecalSystem_Reset(decalsystem);
13968 // if the model is static it doesn't matter what value we give for
13969 // wantnormals and wanttangents, so this logic uses only rules applicable
13970 // to a model, knowing that they are meaningless otherwise
13971 if (ent == r_refdef.scene.worldentity)
13972 RSurf_ActiveWorldEntity();
13974 RSurf_ActiveModelEntity(ent, false, false, false);
13976 decalsystem->lastupdatetime = cl.time;
13977 decal = decalsystem->decals;
13979 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13981 // update vertex positions for animated models
13982 v3f = decalsystem->vertex3f;
13983 c4f = decalsystem->color4f;
13984 t2f = decalsystem->texcoord2f;
13985 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13987 if (!decal->color4ub[0][3])
13990 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13993 // update color values for fading decals
13994 if (decal->lived >= cl_decals_time.value)
13996 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13997 alpha *= (1.0f/255.0f);
14000 alpha = 1.0f/255.0f;
14002 c4f[ 0] = decal->color4ub[0][0] * alpha;
14003 c4f[ 1] = decal->color4ub[0][1] * alpha;
14004 c4f[ 2] = decal->color4ub[0][2] * alpha;
14006 c4f[ 4] = decal->color4ub[1][0] * alpha;
14007 c4f[ 5] = decal->color4ub[1][1] * alpha;
14008 c4f[ 6] = decal->color4ub[1][2] * alpha;
14010 c4f[ 8] = decal->color4ub[2][0] * alpha;
14011 c4f[ 9] = decal->color4ub[2][1] * alpha;
14012 c4f[10] = decal->color4ub[2][2] * alpha;
14015 t2f[0] = decal->texcoord2f[0][0];
14016 t2f[1] = decal->texcoord2f[0][1];
14017 t2f[2] = decal->texcoord2f[1][0];
14018 t2f[3] = decal->texcoord2f[1][1];
14019 t2f[4] = decal->texcoord2f[2][0];
14020 t2f[5] = decal->texcoord2f[2][1];
14022 // update vertex positions for animated models
14023 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
14025 e = rsurface.modelelement3i + 3*decal->triangleindex;
14026 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
14027 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
14028 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
14032 VectorCopy(decal->vertex3f[0], v3f);
14033 VectorCopy(decal->vertex3f[1], v3f + 3);
14034 VectorCopy(decal->vertex3f[2], v3f + 6);
14037 if (r_refdef.fogenabled)
14039 alpha = RSurf_FogVertex(v3f);
14040 VectorScale(c4f, alpha, c4f);
14041 alpha = RSurf_FogVertex(v3f + 3);
14042 VectorScale(c4f + 4, alpha, c4f + 4);
14043 alpha = RSurf_FogVertex(v3f + 6);
14044 VectorScale(c4f + 8, alpha, c4f + 8);
14055 r_refdef.stats.drawndecals += numtris;
14057 // now render the decals all at once
14058 // (this assumes they all use one particle font texture!)
14059 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);
14060 // R_Mesh_ResetTextureState();
14061 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
14062 GL_DepthMask(false);
14063 GL_DepthRange(0, 1);
14064 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
14065 GL_DepthTest(true);
14066 GL_CullFace(GL_NONE);
14067 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
14068 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
14069 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
14073 static void R_DrawModelDecals(void)
14077 // fade faster when there are too many decals
14078 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14079 for (i = 0;i < r_refdef.scene.numentities;i++)
14080 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14082 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
14083 for (i = 0;i < r_refdef.scene.numentities;i++)
14084 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14085 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
14087 R_DecalSystem_ApplySplatEntitiesQueue();
14089 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14090 for (i = 0;i < r_refdef.scene.numentities;i++)
14091 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14093 r_refdef.stats.totaldecals += numdecals;
14095 if (r_showsurfaces.integer)
14098 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
14100 for (i = 0;i < r_refdef.scene.numentities;i++)
14102 if (!r_refdef.viewcache.entityvisible[i])
14104 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14105 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
14109 extern cvar_t mod_collision_bih;
14110 void R_DrawDebugModel(void)
14112 entity_render_t *ent = rsurface.entity;
14113 int i, j, k, l, flagsmask;
14114 const msurface_t *surface;
14115 dp_model_t *model = ent->model;
14118 switch(vid.renderpath)
14120 case RENDERPATH_GL11:
14121 case RENDERPATH_GL13:
14122 case RENDERPATH_GL20:
14123 case RENDERPATH_CGGL:
14125 case RENDERPATH_D3D9:
14126 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14128 case RENDERPATH_D3D10:
14129 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14131 case RENDERPATH_D3D11:
14132 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14136 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
14138 // R_Mesh_ResetTextureState();
14139 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
14140 GL_DepthRange(0, 1);
14141 GL_DepthTest(!r_showdisabledepthtest.integer);
14142 GL_DepthMask(false);
14143 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14145 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
14149 qboolean cullbox = ent == r_refdef.scene.worldentity;
14150 const q3mbrush_t *brush;
14151 const bih_t *bih = &model->collision_bih;
14152 const bih_leaf_t *bihleaf;
14153 float vertex3f[3][3];
14154 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
14156 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
14158 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
14160 switch (bihleaf->type)
14163 brush = model->brush.data_brushes + bihleaf->itemindex;
14164 if (brush->colbrushf && brush->colbrushf->numtriangles)
14166 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);
14167 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
14168 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
14171 case BIH_COLLISIONTRIANGLE:
14172 triangleindex = bihleaf->itemindex;
14173 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
14174 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
14175 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
14176 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);
14177 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14178 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14180 case BIH_RENDERTRIANGLE:
14181 triangleindex = bihleaf->itemindex;
14182 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
14183 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
14184 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
14185 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);
14186 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14187 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14193 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
14195 if (r_showtris.integer || (r_shownormals.value != 0))
14197 if (r_showdisabledepthtest.integer)
14199 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14200 GL_DepthMask(false);
14204 GL_BlendFunc(GL_ONE, GL_ZERO);
14205 GL_DepthMask(true);
14207 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
14209 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
14211 rsurface.texture = R_GetCurrentTexture(surface->texture);
14212 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
14214 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
14215 if (r_showtris.value > 0)
14217 if (!rsurface.texture->currentlayers->depthmask)
14218 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
14219 else if (ent == r_refdef.scene.worldentity)
14220 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
14222 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
14223 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
14224 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
14226 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
14229 if (r_shownormals.value < 0)
14231 qglBegin(GL_LINES);
14232 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14234 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14235 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14236 qglVertex3f(v[0], v[1], v[2]);
14237 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14238 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14239 qglVertex3f(v[0], v[1], v[2]);
14244 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
14246 qglBegin(GL_LINES);
14247 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14249 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14250 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14251 qglVertex3f(v[0], v[1], v[2]);
14252 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14253 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14254 qglVertex3f(v[0], v[1], v[2]);
14258 qglBegin(GL_LINES);
14259 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14261 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14262 GL_Color(0, r_refdef.view.colorscale, 0, 1);
14263 qglVertex3f(v[0], v[1], v[2]);
14264 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
14265 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14266 qglVertex3f(v[0], v[1], v[2]);
14270 qglBegin(GL_LINES);
14271 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14273 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14274 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14275 qglVertex3f(v[0], v[1], v[2]);
14276 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14277 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14278 qglVertex3f(v[0], v[1], v[2]);
14285 rsurface.texture = NULL;
14289 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
14290 int r_maxsurfacelist = 0;
14291 const msurface_t **r_surfacelist = NULL;
14292 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14294 int i, j, endj, flagsmask;
14295 dp_model_t *model = r_refdef.scene.worldmodel;
14296 msurface_t *surfaces;
14297 unsigned char *update;
14298 int numsurfacelist = 0;
14302 if (r_maxsurfacelist < model->num_surfaces)
14304 r_maxsurfacelist = model->num_surfaces;
14306 Mem_Free((msurface_t**)r_surfacelist);
14307 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14310 RSurf_ActiveWorldEntity();
14312 surfaces = model->data_surfaces;
14313 update = model->brushq1.lightmapupdateflags;
14315 // update light styles on this submodel
14316 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14318 model_brush_lightstyleinfo_t *style;
14319 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14321 if (style->value != r_refdef.scene.lightstylevalue[style->style])
14323 int *list = style->surfacelist;
14324 style->value = r_refdef.scene.lightstylevalue[style->style];
14325 for (j = 0;j < style->numsurfaces;j++)
14326 update[list[j]] = true;
14331 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14335 R_DrawDebugModel();
14336 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14340 rsurface.lightmaptexture = NULL;
14341 rsurface.deluxemaptexture = NULL;
14342 rsurface.uselightmaptexture = false;
14343 rsurface.texture = NULL;
14344 rsurface.rtlight = NULL;
14345 numsurfacelist = 0;
14346 // add visible surfaces to draw list
14347 for (i = 0;i < model->nummodelsurfaces;i++)
14349 j = model->sortedmodelsurfaces[i];
14350 if (r_refdef.viewcache.world_surfacevisible[j])
14351 r_surfacelist[numsurfacelist++] = surfaces + j;
14353 // update lightmaps if needed
14354 if (model->brushq1.firstrender)
14356 model->brushq1.firstrender = false;
14357 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14359 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14363 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14364 if (r_refdef.viewcache.world_surfacevisible[j])
14366 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14368 // don't do anything if there were no surfaces
14369 if (!numsurfacelist)
14371 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14374 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14375 GL_AlphaTest(false);
14377 // add to stats if desired
14378 if (r_speeds.integer && !skysurfaces && !depthonly)
14380 r_refdef.stats.world_surfaces += numsurfacelist;
14381 for (j = 0;j < numsurfacelist;j++)
14382 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
14385 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14388 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14390 int i, j, endj, flagsmask;
14391 dp_model_t *model = ent->model;
14392 msurface_t *surfaces;
14393 unsigned char *update;
14394 int numsurfacelist = 0;
14398 if (r_maxsurfacelist < model->num_surfaces)
14400 r_maxsurfacelist = model->num_surfaces;
14402 Mem_Free((msurface_t **)r_surfacelist);
14403 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14406 // if the model is static it doesn't matter what value we give for
14407 // wantnormals and wanttangents, so this logic uses only rules applicable
14408 // to a model, knowing that they are meaningless otherwise
14409 if (ent == r_refdef.scene.worldentity)
14410 RSurf_ActiveWorldEntity();
14411 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14412 RSurf_ActiveModelEntity(ent, false, false, false);
14414 RSurf_ActiveModelEntity(ent, true, true, true);
14415 else if (depthonly)
14417 switch (vid.renderpath)
14419 case RENDERPATH_GL20:
14420 case RENDERPATH_CGGL:
14421 case RENDERPATH_D3D9:
14422 case RENDERPATH_D3D10:
14423 case RENDERPATH_D3D11:
14424 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14426 case RENDERPATH_GL13:
14427 case RENDERPATH_GL11:
14428 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14434 switch (vid.renderpath)
14436 case RENDERPATH_GL20:
14437 case RENDERPATH_CGGL:
14438 case RENDERPATH_D3D9:
14439 case RENDERPATH_D3D10:
14440 case RENDERPATH_D3D11:
14441 RSurf_ActiveModelEntity(ent, true, true, false);
14443 case RENDERPATH_GL13:
14444 case RENDERPATH_GL11:
14445 RSurf_ActiveModelEntity(ent, true, false, false);
14450 surfaces = model->data_surfaces;
14451 update = model->brushq1.lightmapupdateflags;
14453 // update light styles
14454 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14456 model_brush_lightstyleinfo_t *style;
14457 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14459 if (style->value != r_refdef.scene.lightstylevalue[style->style])
14461 int *list = style->surfacelist;
14462 style->value = r_refdef.scene.lightstylevalue[style->style];
14463 for (j = 0;j < style->numsurfaces;j++)
14464 update[list[j]] = true;
14469 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14473 R_DrawDebugModel();
14474 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14478 rsurface.lightmaptexture = NULL;
14479 rsurface.deluxemaptexture = NULL;
14480 rsurface.uselightmaptexture = false;
14481 rsurface.texture = NULL;
14482 rsurface.rtlight = NULL;
14483 numsurfacelist = 0;
14484 // add visible surfaces to draw list
14485 for (i = 0;i < model->nummodelsurfaces;i++)
14486 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14487 // don't do anything if there were no surfaces
14488 if (!numsurfacelist)
14490 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14493 // update lightmaps if needed
14497 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14502 R_BuildLightMap(ent, surfaces + j);
14507 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14509 R_BuildLightMap(ent, surfaces + j);
14510 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14511 GL_AlphaTest(false);
14513 // add to stats if desired
14514 if (r_speeds.integer && !skysurfaces && !depthonly)
14516 r_refdef.stats.entities_surfaces += numsurfacelist;
14517 for (j = 0;j < numsurfacelist;j++)
14518 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14521 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14524 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14526 static texture_t texture;
14527 static msurface_t surface;
14528 const msurface_t *surfacelist = &surface;
14530 // fake enough texture and surface state to render this geometry
14532 texture.update_lastrenderframe = -1; // regenerate this texture
14533 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14534 texture.currentskinframe = skinframe;
14535 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14536 texture.offsetmapping = OFFSETMAPPING_OFF;
14537 texture.offsetscale = 1;
14538 texture.specularscalemod = 1;
14539 texture.specularpowermod = 1;
14541 surface.texture = &texture;
14542 surface.num_triangles = numtriangles;
14543 surface.num_firsttriangle = firsttriangle;
14544 surface.num_vertices = numvertices;
14545 surface.num_firstvertex = firstvertex;
14548 rsurface.texture = R_GetCurrentTexture(surface.texture);
14549 rsurface.lightmaptexture = NULL;
14550 rsurface.deluxemaptexture = NULL;
14551 rsurface.uselightmaptexture = false;
14552 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14555 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)
14557 static msurface_t surface;
14558 const msurface_t *surfacelist = &surface;
14560 // fake enough texture and surface state to render this geometry
14561 surface.texture = texture;
14562 surface.num_triangles = numtriangles;
14563 surface.num_firsttriangle = firsttriangle;
14564 surface.num_vertices = numvertices;
14565 surface.num_firstvertex = firstvertex;
14568 rsurface.texture = R_GetCurrentTexture(surface.texture);
14569 rsurface.lightmaptexture = NULL;
14570 rsurface.deluxemaptexture = NULL;
14571 rsurface.uselightmaptexture = false;
14572 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);