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"
30 #include "dpsoftrast.h"
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 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)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 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"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 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)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
68 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"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
74 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)"};
75 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 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"};
78 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"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 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"};
81 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"};
82 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"};
83 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
84 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
85 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
86 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
87 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
88 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
89 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
90 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)"};
91 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)"};
92 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
93 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
94 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
95 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
97 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
98 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
99 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
101 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
102 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
103 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
104 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."};
105 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
106 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
107 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
108 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."};
109 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
110 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
111 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
112 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
113 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"};
114 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"};
115 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
117 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
118 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
119 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"};
121 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
122 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
123 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
124 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
125 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
126 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
127 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
128 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
130 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)"};
131 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"};
133 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
134 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
137 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
139 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
140 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
141 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
143 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)"};
144 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
145 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
146 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
147 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
148 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)"};
149 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)"};
150 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)"};
151 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
152 cvar_t r_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)"};
153 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)"};
154 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)"};
155 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)"};
157 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)"};
158 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
159 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"};
160 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
161 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
162 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
164 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
165 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
166 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
167 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
169 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
170 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
171 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
172 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
173 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
174 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
175 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
177 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
178 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
179 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
180 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)"};
182 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"};
184 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"};
186 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
188 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
189 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"};
190 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
191 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
192 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
193 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
194 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)"};
195 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
196 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
198 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
199 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"};
201 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)"};
203 extern cvar_t v_glslgamma;
205 extern qboolean v_flipped_state;
207 static struct r_bloomstate_s
212 int bloomwidth, bloomheight;
214 int screentexturewidth, screentextureheight;
215 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
217 int bloomtexturewidth, bloomtextureheight;
218 rtexture_t *texture_bloom;
220 // arrays for rendering the screen passes
221 float screentexcoord2f[8];
222 float bloomtexcoord2f[8];
223 float offsettexcoord2f[8];
225 r_viewport_t viewport;
229 r_waterstate_t r_waterstate;
231 /// shadow volume bsp struct with automatically growing nodes buffer
234 rtexture_t *r_texture_blanknormalmap;
235 rtexture_t *r_texture_white;
236 rtexture_t *r_texture_grey128;
237 rtexture_t *r_texture_black;
238 rtexture_t *r_texture_notexture;
239 rtexture_t *r_texture_whitecube;
240 rtexture_t *r_texture_normalizationcube;
241 rtexture_t *r_texture_fogattenuation;
242 rtexture_t *r_texture_fogheighttexture;
243 rtexture_t *r_texture_gammaramps;
244 unsigned int r_texture_gammaramps_serial;
245 //rtexture_t *r_texture_fogintensity;
246 rtexture_t *r_texture_reflectcube;
248 // TODO: hash lookups?
249 typedef struct cubemapinfo_s
256 int r_texture_numcubemaps;
257 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
259 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
260 unsigned int r_numqueries;
261 unsigned int r_maxqueries;
263 typedef struct r_qwskincache_s
265 char name[MAX_QPATH];
266 skinframe_t *skinframe;
270 static r_qwskincache_t *r_qwskincache;
271 static int r_qwskincache_size;
273 /// vertex coordinates for a quad that covers the screen exactly
274 extern const float r_screenvertex3f[12];
275 extern const float r_d3dscreenvertex3f[12];
276 const float r_screenvertex3f[12] =
283 const float r_d3dscreenvertex3f[12] =
291 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
294 for (i = 0;i < verts;i++)
305 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
308 for (i = 0;i < verts;i++)
318 // FIXME: move this to client?
321 if (gamemode == GAME_NEHAHRA)
323 Cvar_Set("gl_fogenable", "0");
324 Cvar_Set("gl_fogdensity", "0.2");
325 Cvar_Set("gl_fogred", "0.3");
326 Cvar_Set("gl_foggreen", "0.3");
327 Cvar_Set("gl_fogblue", "0.3");
329 r_refdef.fog_density = 0;
330 r_refdef.fog_red = 0;
331 r_refdef.fog_green = 0;
332 r_refdef.fog_blue = 0;
333 r_refdef.fog_alpha = 1;
334 r_refdef.fog_start = 0;
335 r_refdef.fog_end = 16384;
336 r_refdef.fog_height = 1<<30;
337 r_refdef.fog_fadedepth = 128;
338 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
341 static void R_BuildBlankTextures(void)
343 unsigned char data[4];
344 data[2] = 128; // normal X
345 data[1] = 128; // normal Y
346 data[0] = 255; // normal Z
347 data[3] = 128; // height
348 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
353 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
358 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
363 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
366 static void R_BuildNoTexture(void)
369 unsigned char pix[16][16][4];
370 // this makes a light grey/dark grey checkerboard texture
371 for (y = 0;y < 16;y++)
373 for (x = 0;x < 16;x++)
375 if ((y < 8) ^ (x < 8))
391 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
394 static void R_BuildWhiteCube(void)
396 unsigned char data[6*1*1*4];
397 memset(data, 255, sizeof(data));
398 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
401 static void R_BuildNormalizationCube(void)
405 vec_t s, t, intensity;
408 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
409 for (side = 0;side < 6;side++)
411 for (y = 0;y < NORMSIZE;y++)
413 for (x = 0;x < NORMSIZE;x++)
415 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
416 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
451 intensity = 127.0f / sqrt(DotProduct(v, v));
452 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
453 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
454 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
455 data[((side*64+y)*64+x)*4+3] = 255;
459 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
463 static void R_BuildFogTexture(void)
467 unsigned char data1[FOGWIDTH][4];
468 //unsigned char data2[FOGWIDTH][4];
471 r_refdef.fogmasktable_start = r_refdef.fog_start;
472 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
473 r_refdef.fogmasktable_range = r_refdef.fogrange;
474 r_refdef.fogmasktable_density = r_refdef.fog_density;
476 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
477 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
479 d = (x * r - r_refdef.fogmasktable_start);
480 if(developer_extra.integer)
481 Con_DPrintf("%f ", d);
483 if (r_fog_exp2.integer)
484 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
486 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
487 if(developer_extra.integer)
488 Con_DPrintf(" : %f ", alpha);
489 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
490 if(developer_extra.integer)
491 Con_DPrintf(" = %f\n", alpha);
492 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
495 for (x = 0;x < FOGWIDTH;x++)
497 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
502 //data2[x][0] = 255 - b;
503 //data2[x][1] = 255 - b;
504 //data2[x][2] = 255 - b;
507 if (r_texture_fogattenuation)
509 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
510 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
514 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
515 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
519 static void R_BuildFogHeightTexture(void)
521 unsigned char *inpixels;
529 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
530 if (r_refdef.fogheighttexturename[0])
531 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
534 r_refdef.fog_height_tablesize = 0;
535 if (r_texture_fogheighttexture)
536 R_FreeTexture(r_texture_fogheighttexture);
537 r_texture_fogheighttexture = NULL;
538 if (r_refdef.fog_height_table2d)
539 Mem_Free(r_refdef.fog_height_table2d);
540 r_refdef.fog_height_table2d = NULL;
541 if (r_refdef.fog_height_table1d)
542 Mem_Free(r_refdef.fog_height_table1d);
543 r_refdef.fog_height_table1d = NULL;
547 r_refdef.fog_height_tablesize = size;
548 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
549 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
550 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
552 // LordHavoc: now the magic - what is that table2d for? it is a cooked
553 // average fog color table accounting for every fog layer between a point
554 // and the camera. (Note: attenuation is handled separately!)
555 for (y = 0;y < size;y++)
557 for (x = 0;x < size;x++)
563 for (j = x;j <= y;j++)
565 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
571 for (j = x;j >= y;j--)
573 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
578 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
579 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
580 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
581 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
584 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
587 //=======================================================================================================================================================
589 static const char *builtinshaderstring =
590 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
591 "// written by Forest 'LordHavoc' Hale\n"
592 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
594 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
597 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
598 "#define USELIGHTMAP\n"
600 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
601 "#define USEEYEVECTOR\n"
604 "#ifdef USESHADOWMAP2D\n"
605 "# ifdef GL_EXT_gpu_shader4\n"
606 "# extension GL_EXT_gpu_shader4 : enable\n"
608 "# ifdef GL_ARB_texture_gather\n"
609 "# extension GL_ARB_texture_gather : enable\n"
611 "# ifdef GL_AMD_texture_texture4\n"
612 "# extension GL_AMD_texture_texture4 : enable\n"
617 "//#ifdef USESHADOWSAMPLER\n"
618 "//# extension GL_ARB_shadow : enable\n"
621 "//#ifdef __GLSL_CG_DATA_TYPES\n"
622 "//# define myhalf half\n"
623 "//# define myhalf2 half2\n"
624 "//# define myhalf3 half3\n"
625 "//# define myhalf4 half4\n"
627 "# define myhalf float\n"
628 "# define myhalf2 vec2\n"
629 "# define myhalf3 vec3\n"
630 "# define myhalf4 vec4\n"
633 "#ifdef VERTEX_SHADER\n"
634 "uniform mat4 ModelViewProjectionMatrix;\n"
637 "#ifdef MODE_DEPTH_OR_SHADOW\n"
638 "#ifdef VERTEX_SHADER\n"
641 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
644 "#else // !MODE_DEPTH_ORSHADOW\n"
649 "#ifdef MODE_SHOWDEPTH\n"
650 "#ifdef VERTEX_SHADER\n"
653 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
654 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
658 "#ifdef FRAGMENT_SHADER\n"
661 " gl_FragColor = gl_Color;\n"
664 "#else // !MODE_SHOWDEPTH\n"
669 "#ifdef MODE_POSTPROCESS\n"
670 "varying vec2 TexCoord1;\n"
671 "varying vec2 TexCoord2;\n"
673 "#ifdef VERTEX_SHADER\n"
676 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
677 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
679 " TexCoord2 = gl_MultiTexCoord4.xy;\n"
684 "#ifdef FRAGMENT_SHADER\n"
685 "uniform sampler2D Texture_First;\n"
687 "uniform sampler2D Texture_Second;\n"
688 "uniform vec4 BloomColorSubtract;\n"
690 "#ifdef USEGAMMARAMPS\n"
691 "uniform sampler2D Texture_GammaRamps;\n"
693 "#ifdef USESATURATION\n"
694 "uniform float Saturation;\n"
696 "#ifdef USEVIEWTINT\n"
697 "uniform vec4 ViewTintColor;\n"
699 "//uncomment these if you want to use them:\n"
700 "uniform vec4 UserVec1;\n"
701 "uniform vec4 UserVec2;\n"
702 "// uniform vec4 UserVec3;\n"
703 "// uniform vec4 UserVec4;\n"
704 "// uniform float ClientTime;\n"
705 "uniform vec2 PixelSize;\n"
708 " gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
710 " gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
712 "#ifdef USEVIEWTINT\n"
713 " gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
716 "#ifdef USEPOSTPROCESSING\n"
717 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
718 "// 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"
719 " float sobel = 1.0;\n"
720 " // vec2 ts = textureSize(Texture_First, 0);\n"
721 " // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
722 " vec2 px = PixelSize;\n"
723 " vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
724 " vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, 0.0)).rgb;\n"
725 " vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
726 " vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
727 " vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x, 0.0)).rgb;\n"
728 " vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
729 " vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
730 " vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2( 0.0,-px.y)).rgb;\n"
731 " vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
732 " vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
733 " vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2( 0.0, px.y)).rgb;\n"
734 " vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
735 " float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
736 " float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
737 " float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
738 " float px4 = 1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
739 " float px5 = 2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
740 " float px6 = 1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
741 " float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
742 " float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
743 " float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
744 " float py4 = 1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
745 " float py5 = 2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
746 " float py6 = 1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
747 " sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
748 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
749 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
750 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
751 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
752 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
753 " gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
754 " gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
757 "#ifdef USESATURATION\n"
758 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
759 " float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
760 " // 'vampire sight' effect, wheres red is compensated\n"
761 " #ifdef SATURATION_REDCOMPENSATE\n"
762 " float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
763 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
764 " gl_FragColor.r += rboost;\n"
766 " // normal desaturation\n"
767 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
768 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
772 "#ifdef USEGAMMARAMPS\n"
773 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
774 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
775 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
779 "#else // !MODE_POSTPROCESS\n"
784 "#ifdef MODE_GENERIC\n"
785 "#ifdef USEDIFFUSE\n"
786 "varying vec2 TexCoord1;\n"
788 "#ifdef USESPECULAR\n"
789 "varying vec2 TexCoord2;\n"
791 "#ifdef VERTEX_SHADER\n"
794 " gl_FrontColor = gl_Color;\n"
795 "#ifdef USEDIFFUSE\n"
796 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
798 "#ifdef USESPECULAR\n"
799 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
801 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
805 "#ifdef FRAGMENT_SHADER\n"
806 "#ifdef USEDIFFUSE\n"
807 "uniform sampler2D Texture_First;\n"
809 "#ifdef USESPECULAR\n"
810 "uniform sampler2D Texture_Second;\n"
815 "#ifdef USEVIEWTINT\n"
816 " gl_FragColor = gl_Color;\n"
818 " gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
820 "#ifdef USEDIFFUSE\n"
821 " gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
824 "#ifdef USESPECULAR\n"
825 " vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
826 "# ifdef USECOLORMAPPING\n"
827 " gl_FragColor *= tex2;\n"
830 " gl_FragColor += tex2;\n"
832 "# ifdef USEVERTEXTEXTUREBLEND\n"
833 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
838 "#else // !MODE_GENERIC\n"
843 "#ifdef MODE_BLOOMBLUR\n"
844 "varying TexCoord;\n"
845 "#ifdef VERTEX_SHADER\n"
848 " gl_FrontColor = gl_Color;\n"
849 " TexCoord = gl_MultiTexCoord0.xy;\n"
850 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
854 "#ifdef FRAGMENT_SHADER\n"
855 "uniform sampler2D Texture_First;\n"
856 "uniform vec4 BloomBlur_Parameters;\n"
861 " vec2 tc = TexCoord;\n"
862 " vec3 color = texture2D(Texture_First, tc).rgb;\n"
863 " tc += BloomBlur_Parameters.xy;\n"
864 " for (i = 1;i < SAMPLES;i++)\n"
866 " color += texture2D(Texture_First, tc).rgb;\n"
867 " tc += BloomBlur_Parameters.xy;\n"
869 " gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
872 "#else // !MODE_BLOOMBLUR\n"
873 "#ifdef MODE_REFRACTION\n"
874 "varying vec2 TexCoord;\n"
875 "varying vec4 ModelViewProjectionPosition;\n"
876 "uniform mat4 TexMatrix;\n"
877 "#ifdef VERTEX_SHADER\n"
881 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
882 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
883 " ModelViewProjectionPosition = gl_Position;\n"
887 "#ifdef FRAGMENT_SHADER\n"
888 "uniform sampler2D Texture_Normal;\n"
889 "uniform sampler2D Texture_Refraction;\n"
890 "uniform sampler2D Texture_Reflection;\n"
892 "uniform vec4 DistortScaleRefractReflect;\n"
893 "uniform vec4 ScreenScaleRefractReflect;\n"
894 "uniform vec4 ScreenCenterRefractReflect;\n"
895 "uniform vec4 RefractColor;\n"
896 "uniform vec4 ReflectColor;\n"
897 "uniform float ReflectFactor;\n"
898 "uniform float ReflectOffset;\n"
902 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
903 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
904 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
905 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
906 " // FIXME temporary hack to detect the case that the reflection\n"
907 " // gets blackened at edges due to leaving the area that contains actual\n"
909 " // Remove this 'ack once we have a better way to stop this thing from\n"
911 " float 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 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
915 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
916 " gl_FragColor = vec4(texture2D(Texture_Refraction, ScreenTexCoord).rgb, 1.0) * RefractColor;\n"
919 "#else // !MODE_REFRACTION\n"
924 "#ifdef MODE_WATER\n"
925 "varying vec2 TexCoord;\n"
926 "varying vec3 EyeVector;\n"
927 "varying vec4 ModelViewProjectionPosition;\n"
928 "#ifdef VERTEX_SHADER\n"
929 "uniform vec3 EyePosition;\n"
930 "uniform mat4 TexMatrix;\n"
934 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
935 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
936 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
937 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
938 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
939 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
940 " ModelViewProjectionPosition = gl_Position;\n"
944 "#ifdef FRAGMENT_SHADER\n"
945 "uniform sampler2D Texture_Normal;\n"
946 "uniform sampler2D Texture_Refraction;\n"
947 "uniform sampler2D Texture_Reflection;\n"
949 "uniform vec4 DistortScaleRefractReflect;\n"
950 "uniform vec4 ScreenScaleRefractReflect;\n"
951 "uniform vec4 ScreenCenterRefractReflect;\n"
952 "uniform vec4 RefractColor;\n"
953 "uniform vec4 ReflectColor;\n"
954 "uniform float ReflectFactor;\n"
955 "uniform float ReflectOffset;\n"
956 "uniform float ClientTime;\n"
957 "#ifdef USENORMALMAPSCROLLBLEND\n"
958 "uniform vec2 NormalmapScrollBlend;\n"
963 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
964 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
965 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
966 " //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
967 " // slight water animation via 2 layer scrolling (todo: tweak)\n"
968 " #ifdef USENORMALMAPSCROLLBLEND\n"
969 " vec3 normal = texture2D(Texture_Normal, (TexCoord + vec2(0.08, 0.08)*ClientTime*NormalmapScrollBlend.x*0.5)*NormalmapScrollBlend.y).rgb - vec3(1.0);\n"
970 " normal += texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime*NormalmapScrollBlend.x)*NormalmapScrollBlend.y*0.75).rgb;\n"
971 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(normal) + vec3(0.15)).xyxy * DistortScaleRefractReflect;\n"
973 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
975 " // FIXME temporary hack to detect the case that the reflection\n"
976 " // gets blackened at edges due to leaving the area that contains actual\n"
978 " // Remove this 'ack once we have a better way to stop this thing from\n"
980 " float 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 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, -0.01)).rgb) / 0.002);\n"
984 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\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 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, -0.005)).rgb) / 0.002);\n"
989 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
990 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
991 " gl_FragColor = mix(vec4(texture2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, vec4(texture2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
994 "#else // !MODE_WATER\n"
999 "// common definitions between vertex shader and fragment shader:\n"
1001 "varying vec2 TexCoord;\n"
1002 "#ifdef USEVERTEXTEXTUREBLEND\n"
1003 "varying vec2 TexCoord2;\n"
1005 "#ifdef USELIGHTMAP\n"
1006 "varying vec2 TexCoordLightmap;\n"
1009 "#ifdef MODE_LIGHTSOURCE\n"
1010 "varying vec3 CubeVector;\n"
1013 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
1014 "varying vec3 LightVector;\n"
1017 "#ifdef USEEYEVECTOR\n"
1018 "varying vec3 EyeVector;\n"
1021 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
1024 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
1025 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
1026 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
1027 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
1030 "#ifdef USEREFLECTION\n"
1031 "varying vec4 ModelViewProjectionPosition;\n"
1033 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1034 "uniform vec3 LightPosition;\n"
1035 "varying vec4 ModelViewPosition;\n"
1038 "#ifdef MODE_LIGHTSOURCE\n"
1039 "uniform vec3 LightPosition;\n"
1041 "uniform vec3 EyePosition;\n"
1042 "#ifdef MODE_LIGHTDIRECTION\n"
1043 "uniform vec3 LightDir;\n"
1045 "uniform vec4 FogPlane;\n"
1047 "#ifdef USESHADOWMAPORTHO\n"
1048 "varying vec3 ShadowMapTC;\n"
1055 "// 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"
1057 "// fragment shader specific:\n"
1058 "#ifdef FRAGMENT_SHADER\n"
1060 "uniform sampler2D Texture_Normal;\n"
1061 "uniform sampler2D Texture_Color;\n"
1062 "uniform sampler2D Texture_Gloss;\n"
1064 "uniform sampler2D Texture_Glow;\n"
1066 "#ifdef USEVERTEXTEXTUREBLEND\n"
1067 "uniform sampler2D Texture_SecondaryNormal;\n"
1068 "uniform sampler2D Texture_SecondaryColor;\n"
1069 "uniform sampler2D Texture_SecondaryGloss;\n"
1071 "uniform sampler2D Texture_SecondaryGlow;\n"
1074 "#ifdef USECOLORMAPPING\n"
1075 "uniform sampler2D Texture_Pants;\n"
1076 "uniform sampler2D Texture_Shirt;\n"
1079 "#ifdef USEFOGHEIGHTTEXTURE\n"
1080 "uniform sampler2D Texture_FogHeightTexture;\n"
1082 "uniform sampler2D Texture_FogMask;\n"
1084 "#ifdef USELIGHTMAP\n"
1085 "uniform sampler2D Texture_Lightmap;\n"
1087 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1088 "uniform sampler2D Texture_Deluxemap;\n"
1090 "#ifdef USEREFLECTION\n"
1091 "uniform sampler2D Texture_Reflection;\n"
1094 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1095 "uniform sampler2D Texture_ScreenDepth;\n"
1096 "uniform sampler2D Texture_ScreenNormalMap;\n"
1098 "#ifdef USEDEFERREDLIGHTMAP\n"
1099 "uniform sampler2D Texture_ScreenDiffuse;\n"
1100 "uniform sampler2D Texture_ScreenSpecular;\n"
1103 "uniform myhalf3 Color_Pants;\n"
1104 "uniform myhalf3 Color_Shirt;\n"
1105 "uniform myhalf3 FogColor;\n"
1108 "uniform float FogRangeRecip;\n"
1109 "uniform float FogPlaneViewDist;\n"
1110 "uniform float FogHeightFade;\n"
1111 "vec3 FogVertex(vec3 surfacecolor)\n"
1113 " vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1114 " float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1116 "#ifdef USEFOGHEIGHTTEXTURE\n"
1117 " vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1118 " fogfrac = fogheightpixel.a;\n"
1119 " return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1121 "# ifdef USEFOGOUTSIDE\n"
1122 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1124 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1126 " return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1131 "#ifdef USEOFFSETMAPPING\n"
1132 "uniform float OffsetMapping_Scale;\n"
1133 "vec2 OffsetMapping(vec2 TexCoord)\n"
1135 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1136 " // 14 sample relief mapping: linear search and then binary search\n"
1137 " // this basically steps forward a small amount repeatedly until it finds\n"
1138 " // itself inside solid, then jitters forward and back using decreasing\n"
1139 " // amounts to find the impact\n"
1140 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1141 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1142 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1143 " vec3 RT = vec3(TexCoord, 1);\n"
1144 " OffsetVector *= 0.1;\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);\n"
1154 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
1155 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
1156 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
1157 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
1158 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1161 " // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1162 " // this basically moves forward the full distance, and then backs up based\n"
1163 " // on height of samples\n"
1164 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1165 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1166 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1167 " TexCoord += OffsetVector;\n"
1168 " OffsetVector *= 0.5;\n"
1169 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1170 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1171 " return TexCoord;\n"
1174 "#endif // USEOFFSETMAPPING\n"
1176 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1177 "uniform sampler2D Texture_Attenuation;\n"
1178 "uniform samplerCube Texture_Cube;\n"
1181 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1183 "#ifdef USESHADOWMAP2D\n"
1184 "# ifdef USESHADOWSAMPLER\n"
1185 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1187 "uniform sampler2D Texture_ShadowMap2D;\n"
1191 "#ifdef USESHADOWMAPVSDCT\n"
1192 "uniform samplerCube Texture_CubeProjection;\n"
1195 "#if defined(USESHADOWMAP2D)\n"
1196 "uniform vec2 ShadowMap_TextureScale;\n"
1197 "uniform vec4 ShadowMap_Parameters;\n"
1200 "#if defined(USESHADOWMAP2D)\n"
1201 "# ifdef USESHADOWMAPORTHO\n"
1202 "# define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1204 "# ifdef USESHADOWMAPVSDCT\n"
1205 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1207 " vec3 adir = abs(dir);\n"
1208 " vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1209 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1210 " return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1213 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1215 " vec3 adir = abs(dir);\n"
1216 " float ma = adir.z;\n"
1217 " vec4 proj = vec4(dir, 2.5);\n"
1218 " if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1219 " if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1220 " vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1221 " 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"
1225 "#endif // defined(USESHADOWMAP2D)\n"
1227 "# ifdef USESHADOWMAP2D\n"
1228 "float ShadowMapCompare(vec3 dir)\n"
1230 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1233 "# ifdef USESHADOWSAMPLER\n"
1234 "# ifdef USESHADOWMAPPCF\n"
1235 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1236 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1237 " 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"
1239 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1242 "# ifdef USESHADOWMAPPCF\n"
1243 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1244 "# ifdef GL_ARB_texture_gather\n"
1245 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1247 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1249 " vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1250 "# if USESHADOWMAPPCF > 1\n"
1251 " vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1252 " vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1253 " vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1254 " vec4 group4 = step(shadowmaptc.z, texval(-2.0, 0.0));\n"
1255 " vec4 group5 = step(shadowmaptc.z, texval( 0.0, 0.0));\n"
1256 " vec4 group6 = step(shadowmaptc.z, texval( 2.0, 0.0));\n"
1257 " vec4 group7 = step(shadowmaptc.z, texval(-2.0, 2.0));\n"
1258 " vec4 group8 = step(shadowmaptc.z, texval( 0.0, 2.0));\n"
1259 " vec4 group9 = step(shadowmaptc.z, texval( 2.0, 2.0));\n"
1260 " vec4 locols = vec4(group1.ab, group3.ab);\n"
1261 " vec4 hicols = vec4(group7.rg, group9.rg);\n"
1262 " locols.yz += group2.ab;\n"
1263 " hicols.yz += group8.rg;\n"
1264 " vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1265 " vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1266 " mix(locols, hicols, offset.y);\n"
1267 " vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1268 " cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1269 " f = dot(cols, vec4(1.0/25.0));\n"
1271 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1272 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1273 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1274 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1275 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1276 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1277 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1280 "# ifdef GL_EXT_gpu_shader4\n"
1281 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1283 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1285 "# if USESHADOWMAPPCF > 1\n"
1286 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1287 " center *= ShadowMap_TextureScale;\n"
1288 " 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"
1289 " 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"
1290 " 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"
1291 " 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"
1292 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1293 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1295 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1296 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1297 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1298 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1299 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1300 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1304 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1307 "# ifdef USESHADOWMAPORTHO\n"
1308 " return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1314 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1315 "#endif // FRAGMENT_SHADER\n"
1320 "#ifdef MODE_DEFERREDGEOMETRY\n"
1321 "#ifdef VERTEX_SHADER\n"
1322 "uniform mat4 TexMatrix;\n"
1323 "#ifdef USEVERTEXTEXTUREBLEND\n"
1324 "uniform mat4 BackgroundTexMatrix;\n"
1326 "uniform mat4 ModelViewMatrix;\n"
1329 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1330 "#ifdef USEVERTEXTEXTUREBLEND\n"
1331 " gl_FrontColor = gl_Color;\n"
1332 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1335 " // transform unnormalized eye direction into tangent space\n"
1336 "#ifdef USEOFFSETMAPPING\n"
1337 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1338 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1339 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1340 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1343 " VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1344 " VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1345 " VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1346 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1348 "#endif // VERTEX_SHADER\n"
1350 "#ifdef FRAGMENT_SHADER\n"
1353 "#ifdef USEOFFSETMAPPING\n"
1354 " // apply offsetmapping\n"
1355 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1356 "#define TexCoord TexCoordOffset\n"
1359 "#ifdef USEALPHAKILL\n"
1360 " if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1364 "#ifdef USEVERTEXTEXTUREBLEND\n"
1365 " float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1366 " float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1367 " //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1368 " //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1371 "#ifdef USEVERTEXTEXTUREBLEND\n"
1372 " vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1373 " float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1375 " vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1376 " float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1379 " gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1381 "#endif // FRAGMENT_SHADER\n"
1382 "#else // !MODE_DEFERREDGEOMETRY\n"
1387 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1388 "#ifdef VERTEX_SHADER\n"
1389 "uniform mat4 ModelViewMatrix;\n"
1392 " ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1393 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1395 "#endif // VERTEX_SHADER\n"
1397 "#ifdef FRAGMENT_SHADER\n"
1398 "uniform mat4 ViewToLight;\n"
1399 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1400 "uniform vec2 ScreenToDepth;\n"
1401 "uniform myhalf3 DeferredColor_Ambient;\n"
1402 "uniform myhalf3 DeferredColor_Diffuse;\n"
1403 "#ifdef USESPECULAR\n"
1404 "uniform myhalf3 DeferredColor_Specular;\n"
1405 "uniform myhalf SpecularPower;\n"
1407 "uniform myhalf2 PixelToScreenTexCoord;\n"
1410 " // calculate viewspace pixel position\n"
1411 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1413 " position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1414 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1415 " // decode viewspace pixel normal\n"
1416 " myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1417 " myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1418 " // surfacenormal = pixel normal in viewspace\n"
1419 " // LightVector = pixel to light in viewspace\n"
1420 " // CubeVector = position in lightspace\n"
1421 " // eyevector = pixel to view in viewspace\n"
1422 " vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1423 " myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1424 "#ifdef USEDIFFUSE\n"
1425 " // calculate diffuse shading\n"
1426 " myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1427 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1429 "#ifdef USESPECULAR\n"
1430 " // calculate directional shading\n"
1431 " vec3 eyevector = position * -1.0;\n"
1432 "# ifdef USEEXACTSPECULARMATH\n"
1433 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1435 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1436 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1440 "#if defined(USESHADOWMAP2D)\n"
1441 " fade *= ShadowMapCompare(CubeVector);\n"
1444 "#ifdef USEDIFFUSE\n"
1445 " gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1447 " gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1449 "#ifdef USESPECULAR\n"
1450 " gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1452 " gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1455 "# ifdef USECUBEFILTER\n"
1456 " vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1457 " gl_FragData[0].rgb *= cubecolor;\n"
1458 " gl_FragData[1].rgb *= cubecolor;\n"
1461 "#endif // FRAGMENT_SHADER\n"
1462 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1467 "#ifdef VERTEX_SHADER\n"
1468 "uniform mat4 TexMatrix;\n"
1469 "#ifdef USEVERTEXTEXTUREBLEND\n"
1470 "uniform mat4 BackgroundTexMatrix;\n"
1472 "#ifdef MODE_LIGHTSOURCE\n"
1473 "uniform mat4 ModelToLight;\n"
1475 "#ifdef USESHADOWMAPORTHO\n"
1476 "uniform mat4 ShadowMapMatrix;\n"
1480 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1481 " gl_FrontColor = gl_Color;\n"
1483 " // copy the surface texcoord\n"
1484 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1485 "#ifdef USEVERTEXTEXTUREBLEND\n"
1486 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1488 "#ifdef USELIGHTMAP\n"
1489 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1492 "#ifdef MODE_LIGHTSOURCE\n"
1493 " // transform vertex position into light attenuation/cubemap space\n"
1494 " // (-1 to +1 across the light box)\n"
1495 " CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1497 "# ifdef USEDIFFUSE\n"
1498 " // transform unnormalized light direction into tangent space\n"
1499 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
1500 " // normalize it per pixel)\n"
1501 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1502 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1503 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1504 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1508 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1509 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1510 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1511 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1514 " // transform unnormalized eye direction into tangent space\n"
1515 "#ifdef USEEYEVECTOR\n"
1516 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1517 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1518 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1519 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1523 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1524 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1527 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1528 " VectorS = gl_MultiTexCoord1.xyz;\n"
1529 " VectorT = gl_MultiTexCoord2.xyz;\n"
1530 " VectorR = gl_MultiTexCoord3.xyz;\n"
1533 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1534 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1536 "#ifdef USESHADOWMAPORTHO\n"
1537 " ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1540 "#ifdef USEREFLECTION\n"
1541 " ModelViewProjectionPosition = gl_Position;\n"
1544 "#endif // VERTEX_SHADER\n"
1549 "#ifdef FRAGMENT_SHADER\n"
1550 "#ifdef USEDEFERREDLIGHTMAP\n"
1551 "uniform myhalf2 PixelToScreenTexCoord;\n"
1552 "uniform myhalf3 DeferredMod_Diffuse;\n"
1553 "uniform myhalf3 DeferredMod_Specular;\n"
1555 "uniform myhalf3 Color_Ambient;\n"
1556 "uniform myhalf3 Color_Diffuse;\n"
1557 "uniform myhalf3 Color_Specular;\n"
1558 "uniform myhalf SpecularPower;\n"
1560 "uniform myhalf3 Color_Glow;\n"
1562 "uniform myhalf Alpha;\n"
1563 "#ifdef USEREFLECTION\n"
1564 "uniform vec4 DistortScaleRefractReflect;\n"
1565 "uniform vec4 ScreenScaleRefractReflect;\n"
1566 "uniform vec4 ScreenCenterRefractReflect;\n"
1567 "uniform myhalf4 ReflectColor;\n"
1569 "#ifdef USEREFLECTCUBE\n"
1570 "uniform mat4 ModelToReflectCube;\n"
1571 "uniform sampler2D Texture_ReflectMask;\n"
1572 "uniform samplerCube Texture_ReflectCube;\n"
1574 "#ifdef MODE_LIGHTDIRECTION\n"
1575 "uniform myhalf3 LightColor;\n"
1577 "#ifdef MODE_LIGHTSOURCE\n"
1578 "uniform myhalf3 LightColor;\n"
1582 "#ifdef USEOFFSETMAPPING\n"
1583 " // apply offsetmapping\n"
1584 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1585 "#define TexCoord TexCoordOffset\n"
1588 " // combine the diffuse textures (base, pants, shirt)\n"
1589 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1590 "#ifdef USEALPHAKILL\n"
1591 " if (color.a < 0.5)\n"
1594 " color.a *= Alpha;\n"
1595 "#ifdef USECOLORMAPPING\n"
1596 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1598 "#ifdef USEVERTEXTEXTUREBLEND\n"
1599 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1600 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1601 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1602 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1604 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1607 " // get the surface normal\n"
1608 "#ifdef USEVERTEXTEXTUREBLEND\n"
1609 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1611 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1614 " // get the material colors\n"
1615 " myhalf3 diffusetex = color.rgb;\n"
1616 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1617 "# ifdef USEVERTEXTEXTUREBLEND\n"
1618 " myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1620 " myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1624 "#ifdef USEREFLECTCUBE\n"
1625 " vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1626 " vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1627 " vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1628 " diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1634 "#ifdef MODE_LIGHTSOURCE\n"
1635 " // light source\n"
1636 "#ifdef USEDIFFUSE\n"
1637 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1638 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1639 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1640 "#ifdef USESPECULAR\n"
1641 "#ifdef USEEXACTSPECULARMATH\n"
1642 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1644 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1645 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1647 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1650 " color.rgb = diffusetex * Color_Ambient;\n"
1652 " color.rgb *= LightColor;\n"
1653 " color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1654 "#if defined(USESHADOWMAP2D)\n"
1655 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1657 "# ifdef USECUBEFILTER\n"
1658 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1660 "#endif // MODE_LIGHTSOURCE\n"
1665 "#ifdef MODE_LIGHTDIRECTION\n"
1667 "#ifdef USEDIFFUSE\n"
1668 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1670 "#define lightcolor LightColor\n"
1671 "#endif // MODE_LIGHTDIRECTION\n"
1672 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1674 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1675 " myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1676 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1677 " // convert modelspace light vector to tangentspace\n"
1678 " myhalf3 lightnormal;\n"
1679 " lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1680 " lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1681 " lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1682 " lightnormal = normalize(lightnormal); // VectorS/T/R are not always perfectly normalized, and EXACTSPECULARMATH is very picky about this\n"
1683 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1684 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1685 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1686 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1687 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1688 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1689 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1690 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1691 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1692 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1693 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1694 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1696 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1697 " myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1698 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1704 "#ifdef MODE_FAKELIGHT\n"
1706 "myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
1707 "myhalf3 lightcolor = myhalf3(1.0);\n"
1708 "#endif // MODE_FAKELIGHT\n"
1713 "#ifdef MODE_LIGHTMAP\n"
1714 " color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1715 "#endif // MODE_LIGHTMAP\n"
1716 "#ifdef MODE_VERTEXCOLOR\n"
1717 " color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1718 "#endif // MODE_VERTEXCOLOR\n"
1719 "#ifdef MODE_FLATCOLOR\n"
1720 " color.rgb = diffusetex * Color_Ambient;\n"
1721 "#endif // MODE_FLATCOLOR\n"
1727 "# ifdef USEDIFFUSE\n"
1728 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1729 "# ifdef USESPECULAR\n"
1730 "# ifdef USEEXACTSPECULARMATH\n"
1731 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1733 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1734 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1736 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1738 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1741 " color.rgb = diffusetex * Color_Ambient;\n"
1745 "#ifdef USESHADOWMAPORTHO\n"
1746 " color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1749 "#ifdef USEDEFERREDLIGHTMAP\n"
1750 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1751 " color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1752 " color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1756 "#ifdef USEVERTEXTEXTUREBLEND\n"
1757 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1759 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1764 " color.rgb = FogVertex(color.rgb);\n"
1767 " // 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"
1768 "#ifdef USEREFLECTION\n"
1769 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1770 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1771 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1772 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1773 " // FIXME temporary hack to detect the case that the reflection\n"
1774 " // gets blackened at edges due to leaving the area that contains actual\n"
1776 " // Remove this 'ack once we have a better way to stop this thing from\n"
1778 " float 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 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1782 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1783 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1786 " gl_FragColor = vec4(color);\n"
1788 "#endif // FRAGMENT_SHADER\n"
1790 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1791 "#endif // !MODE_DEFERREDGEOMETRY\n"
1792 "#endif // !MODE_WATER\n"
1793 "#endif // !MODE_REFRACTION\n"
1794 "#endif // !MODE_BLOOMBLUR\n"
1795 "#endif // !MODE_GENERIC\n"
1796 "#endif // !MODE_POSTPROCESS\n"
1797 "#endif // !MODE_SHOWDEPTH\n"
1798 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1802 =========================================================================================================================================================
1806 =========================================================================================================================================================
1810 =========================================================================================================================================================
1814 =========================================================================================================================================================
1818 =========================================================================================================================================================
1822 =========================================================================================================================================================
1826 =========================================================================================================================================================
1829 const char *builtincgshaderstring =
1830 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1831 "// written by Forest 'LordHavoc' Hale\n"
1832 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1834 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1835 "#if defined(USEREFLECTION)\n"
1836 "#undef USESHADOWMAPORTHO\n"
1839 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1842 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1843 "#define USELIGHTMAP\n"
1845 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
1846 "#define USEEYEVECTOR\n"
1849 "#ifdef FRAGMENT_SHADER\n"
1851 "//#undef USESHADOWMAPPCF\n"
1852 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1853 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1855 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1859 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1860 "#ifdef VERTEX_SHADER\n"
1863 "float4 gl_Vertex : POSITION,\n"
1864 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1865 "out float4 gl_Position : POSITION,\n"
1866 "out float Depth : TEXCOORD0\n"
1869 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1870 " Depth = gl_Position.z;\n"
1874 "#ifdef FRAGMENT_SHADER\n"
1877 "float Depth : TEXCOORD0,\n"
1878 "out float4 gl_FragColor : COLOR\n"
1881 "// float4 temp = float4(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0),0.0);\n"
1882 " float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
1883 " temp.yz -= floor(temp.yz);\n"
1884 " gl_FragColor = temp;\n"
1885 "// gl_FragColor = float4(Depth,0,0,0);\n"
1888 "#else // !MODE_DEPTH_ORSHADOW\n"
1893 "#ifdef MODE_SHOWDEPTH\n"
1894 "#ifdef VERTEX_SHADER\n"
1897 "float4 gl_Vertex : POSITION,\n"
1898 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1899 "out float4 gl_Position : POSITION,\n"
1900 "out float4 gl_FrontColor : COLOR0\n"
1903 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1904 " gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1908 "#ifdef FRAGMENT_SHADER\n"
1911 "float4 gl_FrontColor : COLOR0,\n"
1912 "out float4 gl_FragColor : COLOR\n"
1915 " gl_FragColor = gl_FrontColor;\n"
1918 "#else // !MODE_SHOWDEPTH\n"
1923 "#ifdef MODE_POSTPROCESS\n"
1925 "#ifdef VERTEX_SHADER\n"
1928 "float4 gl_Vertex : POSITION,\n"
1929 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1930 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1931 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1932 "out float4 gl_Position : POSITION,\n"
1933 "out float2 TexCoord1 : TEXCOORD0,\n"
1934 "out float2 TexCoord2 : TEXCOORD1\n"
1937 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1938 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
1940 " TexCoord2 = gl_MultiTexCoord4.xy;\n"
1945 "#ifdef FRAGMENT_SHADER\n"
1948 "float2 TexCoord1 : TEXCOORD0,\n"
1949 "float2 TexCoord2 : TEXCOORD1,\n"
1950 "uniform sampler Texture_First : register(s0),\n"
1952 "uniform sampler Texture_Second : register(s1),\n"
1954 "#ifdef USEGAMMARAMPS\n"
1955 "uniform sampler Texture_GammaRamps : register(s2),\n"
1957 "#ifdef USESATURATION\n"
1958 "uniform float Saturation : register(c30),\n"
1960 "#ifdef USEVIEWTINT\n"
1961 "uniform float4 ViewTintColor : register(c41),\n"
1963 "uniform float4 UserVec1 : register(c37),\n"
1964 "uniform float4 UserVec2 : register(c38),\n"
1965 "uniform float4 UserVec3 : register(c39),\n"
1966 "uniform float4 UserVec4 : register(c40),\n"
1967 "uniform float ClientTime : register(c2),\n"
1968 "uniform float2 PixelSize : register(c25),\n"
1969 "uniform float4 BloomColorSubtract : register(c43),\n"
1970 "out float4 gl_FragColor : COLOR\n"
1973 " gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1975 " gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
1977 "#ifdef USEVIEWTINT\n"
1978 " gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1981 "#ifdef USEPOSTPROCESSING\n"
1982 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1983 "// 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"
1984 " float sobel = 1.0;\n"
1985 " // float2 ts = textureSize(Texture_First, 0);\n"
1986 " // float2 px = float2(1/ts.x, 1/ts.y);\n"
1987 " float2 px = PixelSize;\n"
1988 " float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1989 " float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x, 0.0)).rgb;\n"
1990 " float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1991 " float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1992 " float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x, 0.0)).rgb;\n"
1993 " float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1994 " float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1995 " float3 y2 = tex2D(Texture_First, TexCoord1 + float2( 0.0,-px.y)).rgb;\n"
1996 " float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1997 " float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1998 " float3 y5 = tex2D(Texture_First, TexCoord1 + float2( 0.0, px.y)).rgb;\n"
1999 " float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2000 " float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
2001 " float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
2002 " float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
2003 " float px4 = 1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
2004 " float px5 = 2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
2005 " float px6 = 1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
2006 " float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
2007 " float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
2008 " float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
2009 " float py4 = 1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
2010 " float py5 = 2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
2011 " float py6 = 1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
2012 " sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
2013 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2014 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2015 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2016 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107, 0.707107)) * UserVec1.y;\n"
2017 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990, 0.891007)) * UserVec1.y;\n"
2018 " gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2019 " gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2022 "#ifdef USESATURATION\n"
2023 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2024 " float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2025 " // 'vampire sight' effect, wheres red is compensated\n"
2026 " #ifdef SATURATION_REDCOMPENSATE\n"
2027 " float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
2028 " gl_FragColor.rgb = mix(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2029 " gl_FragColor.r += r;\n"
2031 " // normal desaturation\n"
2032 " //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2033 " gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2037 "#ifdef USEGAMMARAMPS\n"
2038 " gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2039 " gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2040 " gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2044 "#else // !MODE_POSTPROCESS\n"
2049 "#ifdef MODE_GENERIC\n"
2050 "#ifdef VERTEX_SHADER\n"
2053 "float4 gl_Vertex : POSITION,\n"
2054 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2055 "float4 gl_Color : COLOR0,\n"
2056 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2057 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2058 "out float4 gl_Position : POSITION,\n"
2059 "#ifdef USEDIFFUSE\n"
2060 "out float2 TexCoord1 : TEXCOORD0,\n"
2062 "#ifdef USESPECULAR\n"
2063 "out float2 TexCoord2 : TEXCOORD1,\n"
2065 "out float4 gl_FrontColor : COLOR\n"
2069 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2071 " gl_FrontColor = gl_Color; // Cg is forward\n"
2073 "#ifdef USEDIFFUSE\n"
2074 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
2076 "#ifdef USESPECULAR\n"
2077 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
2079 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2083 "#ifdef FRAGMENT_SHADER\n"
2087 "float4 gl_FrontColor : COLOR0,\n"
2088 "float2 TexCoord1 : TEXCOORD0,\n"
2089 "float2 TexCoord2 : TEXCOORD1,\n"
2090 "#ifdef USEDIFFUSE\n"
2091 "uniform sampler Texture_First : register(s0),\n"
2093 "#ifdef USESPECULAR\n"
2094 "uniform sampler Texture_Second : register(s1),\n"
2096 "out float4 gl_FragColor : COLOR\n"
2099 "#ifdef USEVIEWTINT\n"
2100 " gl_FragColor = gl_FrontColor;\n"
2102 " gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
2104 "#ifdef USEDIFFUSE\n"
2105 " gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2108 "#ifdef USESPECULAR\n"
2109 " float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2110 "# ifdef USECOLORMAPPING\n"
2111 " gl_FragColor *= tex2;\n"
2114 " gl_FragColor += tex2;\n"
2116 "# ifdef USEVERTEXTEXTUREBLEND\n"
2117 " gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2122 "#else // !MODE_GENERIC\n"
2127 "#ifdef MODE_BLOOMBLUR\n"
2128 "#ifdef VERTEX_SHADER\n"
2131 "float4 gl_Vertex : POSITION,\n"
2132 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2133 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2134 "out float4 gl_Position : POSITION,\n"
2135 "out float2 TexCoord : TEXCOORD0\n"
2138 " TexCoord = gl_MultiTexCoord0.xy;\n"
2139 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2143 "#ifdef FRAGMENT_SHADER\n"
2147 "float2 TexCoord : TEXCOORD0,\n"
2148 "uniform sampler Texture_First : register(s0),\n"
2149 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2150 "out float4 gl_FragColor : COLOR\n"
2154 " float2 tc = TexCoord;\n"
2155 " float3 color = tex2D(Texture_First, tc).rgb;\n"
2156 " tc += BloomBlur_Parameters.xy;\n"
2157 " for (i = 1;i < SAMPLES;i++)\n"
2159 " color += tex2D(Texture_First, tc).rgb;\n"
2160 " tc += BloomBlur_Parameters.xy;\n"
2162 " gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2165 "#else // !MODE_BLOOMBLUR\n"
2166 "#ifdef MODE_REFRACTION\n"
2167 "#ifdef VERTEX_SHADER\n"
2170 "float4 gl_Vertex : POSITION,\n"
2171 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2172 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2173 "uniform float4x4 TexMatrix : register(c0),\n"
2174 "uniform float3 EyePosition : register(c24),\n"
2175 "out float4 gl_Position : POSITION,\n"
2176 "out float2 TexCoord : TEXCOORD0,\n"
2177 "out float3 EyeVector : TEXCOORD1,\n"
2178 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2181 " TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2182 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2183 " ModelViewProjectionPosition = gl_Position;\n"
2187 "#ifdef FRAGMENT_SHADER\n"
2190 "float2 TexCoord : TEXCOORD0,\n"
2191 "float3 EyeVector : TEXCOORD1,\n"
2192 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2193 "uniform sampler Texture_Normal : register(s0),\n"
2194 "uniform sampler Texture_Refraction : register(s3),\n"
2195 "uniform sampler Texture_Reflection : register(s7),\n"
2196 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2197 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2198 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2199 "uniform float4 RefractColor : register(c29),\n"
2200 "out float4 gl_FragColor : COLOR\n"
2203 " float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2204 " //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"
2205 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2206 " float2 ScreenTexCoord = SafeScreenTexCoord + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy;\n"
2207 " // FIXME temporary hack to detect the case that the reflection\n"
2208 " // gets blackened at edges due to leaving the area that contains actual\n"
2210 " // Remove this 'ack once we have a better way to stop this thing from\n"
2212 " float 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 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2216 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2217 " gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
2220 "#else // !MODE_REFRACTION\n"
2225 "#ifdef MODE_WATER\n"
2226 "#ifdef VERTEX_SHADER\n"
2230 "float4 gl_Vertex : POSITION,\n"
2231 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2232 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2233 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2234 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2235 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2236 "uniform float4x4 TexMatrix : register(c0),\n"
2237 "uniform float3 EyePosition : register(c24),\n"
2238 "out float4 gl_Position : POSITION,\n"
2239 "out float2 TexCoord : TEXCOORD0,\n"
2240 "out float3 EyeVector : TEXCOORD1,\n"
2241 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2244 " TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2245 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2246 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2247 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2248 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2249 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2250 " ModelViewProjectionPosition = gl_Position;\n"
2254 "#ifdef FRAGMENT_SHADER\n"
2257 "float2 TexCoord : TEXCOORD0,\n"
2258 "float3 EyeVector : TEXCOORD1,\n"
2259 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2260 "uniform sampler Texture_Normal : register(s0),\n"
2261 "uniform sampler Texture_Refraction : register(s3),\n"
2262 "uniform sampler Texture_Reflection : register(s7),\n"
2263 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2264 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2265 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2266 "uniform float4 RefractColor : register(c29),\n"
2267 "uniform float4 ReflectColor : register(c26),\n"
2268 "uniform float ReflectFactor : register(c27),\n"
2269 "uniform float ReflectOffset : register(c28),\n"
2270 "out float4 gl_FragColor : COLOR\n"
2273 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2274 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2275 " float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2276 " //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2277 " float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2278 " // FIXME temporary hack to detect the case that the reflection\n"
2279 " // gets blackened at edges due to leaving the area that contains actual\n"
2281 " // Remove this 'ack once we have a better way to stop this thing from\n"
2283 " float 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 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2287 " ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\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 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2292 " ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2293 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2294 " gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
2297 "#else // !MODE_WATER\n"
2302 "// 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"
2304 "// fragment shader specific:\n"
2305 "#ifdef FRAGMENT_SHADER\n"
2308 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2311 "#ifdef USEFOGHEIGHTTEXTURE\n"
2312 " float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2313 " fogfrac = fogheightpixel.a;\n"
2314 " return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2316 "# ifdef USEFOGOUTSIDE\n"
2317 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2319 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2321 " return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2326 "#ifdef USEOFFSETMAPPING\n"
2327 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2329 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2330 " // 14 sample relief mapping: linear search and then binary search\n"
2331 " // this basically steps forward a small amount repeatedly until it finds\n"
2332 " // itself inside solid, then jitters forward and back using decreasing\n"
2333 " // amounts to find the impact\n"
2334 " //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2335 " //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2336 " float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2337 " float3 RT = float3(TexCoord, 1);\n"
2338 " OffsetVector *= 0.1;\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);\n"
2348 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
2349 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
2350 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
2351 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
2352 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2355 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2356 " // this basically moves forward the full distance, and then backs up based\n"
2357 " // on height of samples\n"
2358 " //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2359 " //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2360 " float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2361 " TexCoord += OffsetVector;\n"
2362 " OffsetVector *= 0.333;\n"
2363 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2364 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2365 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2366 " return TexCoord;\n"
2369 "#endif // USEOFFSETMAPPING\n"
2371 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2372 "#if defined(USESHADOWMAP2D)\n"
2373 "# ifdef USESHADOWMAPORTHO\n"
2374 "# define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2376 "# ifdef USESHADOWMAPVSDCT\n"
2377 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2379 " float3 adir = abs(dir);\n"
2380 " float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2381 " float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2382 " return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2385 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2387 " float3 adir = abs(dir);\n"
2388 " float ma = adir.z;\n"
2389 " float4 proj = float4(dir, 2.5);\n"
2390 " if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2391 " if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2393 " 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"
2395 " float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2396 " 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"
2401 "#endif // defined(USESHADOWMAP2D)\n"
2403 "# ifdef USESHADOWMAP2D\n"
2404 "#ifdef USESHADOWMAPVSDCT\n"
2405 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2407 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2410 "#ifdef USESHADOWMAPVSDCT\n"
2411 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2413 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2417 "# ifdef USESHADOWSAMPLER\n"
2418 "# ifdef USESHADOWMAPPCF\n"
2419 "# define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r \n"
2420 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2421 " 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"
2423 " f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2426 "# ifdef USESHADOWMAPPCF\n"
2427 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2428 "# ifdef GL_ARB_texture_gather\n"
2429 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2431 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2433 " float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2434 "# if USESHADOWMAPPCF > 1\n"
2435 " float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2436 " float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2437 " float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2438 " float4 group4 = step(shadowmaptc.z, texval(-2.0, 0.0));\n"
2439 " float4 group5 = step(shadowmaptc.z, texval( 0.0, 0.0));\n"
2440 " float4 group6 = step(shadowmaptc.z, texval( 2.0, 0.0));\n"
2441 " float4 group7 = step(shadowmaptc.z, texval(-2.0, 2.0));\n"
2442 " float4 group8 = step(shadowmaptc.z, texval( 0.0, 2.0));\n"
2443 " float4 group9 = step(shadowmaptc.z, texval( 2.0, 2.0));\n"
2444 " float4 locols = float4(group1.ab, group3.ab);\n"
2445 " float4 hicols = float4(group7.rg, group9.rg);\n"
2446 " locols.yz += group2.ab;\n"
2447 " hicols.yz += group8.rg;\n"
2448 " float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2449 " float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2450 " lerp(locols, hicols, offset.y);\n"
2451 " float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2452 " cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2453 " f = dot(cols, float4(1.0/25.0));\n"
2455 " float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2456 " float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2457 " float4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
2458 " float4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
2459 " float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2460 " lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2461 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2464 "# ifdef GL_EXT_gpu_shader4\n"
2465 "# define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2467 "# define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r \n"
2469 "# if USESHADOWMAPPCF > 1\n"
2470 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2471 " center *= ShadowMap_TextureScale;\n"
2472 " 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"
2473 " 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"
2474 " 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"
2475 " 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"
2476 " float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2477 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2479 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2480 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2481 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2482 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2483 " float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2484 " f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2488 " f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2491 "# ifdef USESHADOWMAPORTHO\n"
2492 " return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2498 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2499 "#endif // FRAGMENT_SHADER\n"
2504 "#ifdef MODE_DEFERREDGEOMETRY\n"
2505 "#ifdef VERTEX_SHADER\n"
2508 "float4 gl_Vertex : POSITION,\n"
2509 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2510 "#ifdef USEVERTEXTEXTUREBLEND\n"
2511 "float4 gl_Color : COLOR0,\n"
2513 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2514 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2515 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2516 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2517 "uniform float4x4 TexMatrix : register(c0),\n"
2518 "#ifdef USEVERTEXTEXTUREBLEND\n"
2519 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2521 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2522 "#ifdef USEOFFSETMAPPING\n"
2523 "uniform float3 EyePosition : register(c24),\n"
2525 "out float4 gl_Position : POSITION,\n"
2526 "#ifdef USEVERTEXTEXTUREBLEND\n"
2527 "out float4 gl_FrontColor : COLOR,\n"
2529 "out float4 TexCoordBoth : TEXCOORD0,\n"
2530 "#ifdef USEOFFSETMAPPING\n"
2531 "out float3 EyeVector : TEXCOORD2,\n"
2533 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2534 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2535 "out float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\n"
2538 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2539 "#ifdef USEVERTEXTEXTUREBLEND\n"
2541 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2543 " gl_FrontColor = gl_Color; // Cg is forward\n"
2545 " TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2548 " // transform unnormalized eye direction into tangent space\n"
2549 "#ifdef USEOFFSETMAPPING\n"
2550 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2551 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2552 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2553 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2556 " VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2557 " VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2558 " VectorR.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2559 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2560 " VectorR.w = gl_Position.z;\n"
2562 "#endif // VERTEX_SHADER\n"
2564 "#ifdef FRAGMENT_SHADER\n"
2567 "float4 TexCoordBoth : TEXCOORD0,\n"
2568 "float3 EyeVector : TEXCOORD2,\n"
2569 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2570 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2571 "float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
2572 "uniform sampler Texture_Normal : register(s0),\n"
2573 "#ifdef USEALPHAKILL\n"
2574 "uniform sampler Texture_Color : register(s1),\n"
2576 "uniform sampler Texture_Gloss : register(s2),\n"
2577 "#ifdef USEVERTEXTEXTUREBLEND\n"
2578 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2579 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2581 "#ifdef USEOFFSETMAPPING\n"
2582 "uniform float OffsetMapping_Scale : register(c24),\n"
2584 "uniform half SpecularPower : register(c36),\n"
2586 "out float4 gl_FragData0 : COLOR0,\n"
2587 "out float4 gl_FragData1 : COLOR1\n"
2589 "out float4 gl_FragColor : COLOR\n"
2593 " float2 TexCoord = TexCoordBoth.xy;\n"
2594 "#ifdef USEOFFSETMAPPING\n"
2595 " // apply offsetmapping\n"
2596 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2597 "#define TexCoord TexCoordOffset\n"
2600 "#ifdef USEALPHAKILL\n"
2601 " if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2605 "#ifdef USEVERTEXTEXTUREBLEND\n"
2606 " float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2607 " float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2608 " //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2609 " //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2612 "#ifdef USEVERTEXTEXTUREBLEND\n"
2613 " float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2614 " float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2616 " float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2617 " float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2621 " 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"
2622 " float Depth = VectorR.w / 256.0;\n"
2623 " float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
2624 "// float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
2625 " depthcolor.yz -= floor(depthcolor.yz);\n"
2626 " gl_FragData1 = depthcolor;\n"
2628 " gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2631 "#endif // FRAGMENT_SHADER\n"
2632 "#else // !MODE_DEFERREDGEOMETRY\n"
2637 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2638 "#ifdef VERTEX_SHADER\n"
2641 "float4 gl_Vertex : POSITION,\n"
2642 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2643 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2644 "out float4 gl_Position : POSITION,\n"
2645 "out float4 ModelViewPosition : TEXCOORD0\n"
2648 " ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2649 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2651 "#endif // VERTEX_SHADER\n"
2653 "#ifdef FRAGMENT_SHADER\n"
2657 "float2 Pixel : VPOS,\n"
2659 "float2 Pixel : WPOS,\n"
2661 "float4 ModelViewPosition : TEXCOORD0,\n"
2662 "uniform float4x4 ViewToLight : register(c44),\n"
2663 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2664 "uniform float3 LightPosition : register(c23),\n"
2665 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2666 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2667 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2668 "#ifdef USESPECULAR\n"
2669 "uniform half3 DeferredColor_Specular : register(c11),\n"
2670 "uniform half SpecularPower : register(c36),\n"
2672 "uniform sampler Texture_Attenuation : register(s9),\n"
2673 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2674 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2676 "#ifdef USECUBEFILTER\n"
2677 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2680 "#ifdef USESHADOWMAP2D\n"
2681 "# ifdef USESHADOWSAMPLER\n"
2682 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2684 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2688 "#ifdef USESHADOWMAPVSDCT\n"
2689 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2692 "#if defined(USESHADOWMAP2D)\n"
2693 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2694 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2697 "out float4 gl_FragData0 : COLOR0,\n"
2698 "out float4 gl_FragData1 : COLOR1\n"
2701 " // calculate viewspace pixel position\n"
2702 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2703 " //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2704 " float3 position;\n"
2706 " position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
2708 " position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2710 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2711 " // decode viewspace pixel normal\n"
2712 " half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2713 " half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2714 " // surfacenormal = pixel normal in viewspace\n"
2715 " // LightVector = pixel to light in viewspace\n"
2716 " // CubeVector = position in lightspace\n"
2717 " // eyevector = pixel to view in viewspace\n"
2718 " float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2719 " half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2720 "#ifdef USEDIFFUSE\n"
2721 " // calculate diffuse shading\n"
2722 " half3 lightnormal = half3(normalize(LightPosition - position));\n"
2723 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2725 "#ifdef USESPECULAR\n"
2726 " // calculate directional shading\n"
2727 " float3 eyevector = position * -1.0;\n"
2728 "# ifdef USEEXACTSPECULARMATH\n"
2729 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
2731 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2732 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
2736 "#if defined(USESHADOWMAP2D)\n"
2737 " fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2738 "#ifdef USESHADOWMAPVSDCT\n"
2739 ", Texture_CubeProjection\n"
2744 "#ifdef USEDIFFUSE\n"
2745 " gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2747 " gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2749 "#ifdef USESPECULAR\n"
2750 " gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2752 " gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2755 "# ifdef USECUBEFILTER\n"
2756 " float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2757 " gl_FragData0.rgb *= cubecolor;\n"
2758 " gl_FragData1.rgb *= cubecolor;\n"
2761 "#endif // FRAGMENT_SHADER\n"
2762 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2767 "#ifdef VERTEX_SHADER\n"
2770 "float4 gl_Vertex : POSITION,\n"
2771 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2772 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2773 "float4 gl_Color : COLOR0,\n"
2775 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2776 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2777 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2778 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2779 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2781 "uniform float3 EyePosition : register(c24),\n"
2782 "uniform float4x4 TexMatrix : register(c0),\n"
2783 "#ifdef USEVERTEXTEXTUREBLEND\n"
2784 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2786 "#ifdef MODE_LIGHTSOURCE\n"
2787 "uniform float4x4 ModelToLight : register(c20),\n"
2789 "#ifdef MODE_LIGHTSOURCE\n"
2790 "uniform float3 LightPosition : register(c27),\n"
2792 "#ifdef MODE_LIGHTDIRECTION\n"
2793 "uniform float3 LightDir : register(c26),\n"
2795 "uniform float4 FogPlane : register(c25),\n"
2796 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2797 "uniform float3 LightPosition : register(c27),\n"
2799 "#ifdef USESHADOWMAPORTHO\n"
2800 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2802 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2803 "out float4 gl_FrontColor : COLOR,\n"
2805 "out float4 TexCoordBoth : TEXCOORD0,\n"
2806 "#ifdef USELIGHTMAP\n"
2807 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2809 "#ifdef USEEYEVECTOR\n"
2810 "out float3 EyeVector : TEXCOORD2,\n"
2812 "#ifdef USEREFLECTION\n"
2813 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2816 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2818 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE) || defined(USEDIFFUSE)\n"
2819 "out float3 LightVector : TEXCOORD1,\n"
2821 "#ifdef MODE_LIGHTSOURCE\n"
2822 "out float3 CubeVector : TEXCOORD3,\n"
2824 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2825 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2826 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2827 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2829 "#ifdef USESHADOWMAPORTHO\n"
2830 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2832 "out float4 gl_Position : POSITION\n"
2835 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2837 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2839 " gl_FrontColor = gl_Color; // Cg is forward\n"
2842 " // copy the surface texcoord\n"
2843 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2844 "#ifdef USEVERTEXTEXTUREBLEND\n"
2845 " TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2847 "#ifdef USELIGHTMAP\n"
2848 " TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2851 "#ifdef MODE_LIGHTSOURCE\n"
2852 " // transform vertex position into light attenuation/cubemap space\n"
2853 " // (-1 to +1 across the light box)\n"
2854 " CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2856 "# ifdef USEDIFFUSE\n"
2857 " // transform unnormalized light direction into tangent space\n"
2858 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
2859 " // normalize it per pixel)\n"
2860 " float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2861 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2862 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2863 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2867 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2868 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2869 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2870 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2873 " // transform unnormalized eye direction into tangent space\n"
2874 "#ifdef USEEYEVECTOR\n"
2875 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2876 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2877 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2878 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2882 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2883 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2886 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2887 " VectorS = gl_MultiTexCoord1.xyz;\n"
2888 " VectorT = gl_MultiTexCoord2.xyz;\n"
2889 " VectorR = gl_MultiTexCoord3.xyz;\n"
2892 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2893 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2895 "#ifdef USESHADOWMAPORTHO\n"
2896 " ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2899 "#ifdef USEREFLECTION\n"
2900 " ModelViewProjectionPosition = gl_Position;\n"
2903 "#endif // VERTEX_SHADER\n"
2908 "#ifdef FRAGMENT_SHADER\n"
2911 "#ifdef USEDEFERREDLIGHTMAP\n"
2913 "float2 Pixel : VPOS,\n"
2915 "float2 Pixel : WPOS,\n"
2918 "float4 gl_FrontColor : COLOR,\n"
2919 "float4 TexCoordBoth : TEXCOORD0,\n"
2920 "#ifdef USELIGHTMAP\n"
2921 "float2 TexCoordLightmap : TEXCOORD1,\n"
2923 "#ifdef USEEYEVECTOR\n"
2924 "float3 EyeVector : TEXCOORD2,\n"
2926 "#ifdef USEREFLECTION\n"
2927 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2930 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2932 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2933 "float3 LightVector : TEXCOORD1,\n"
2935 "#ifdef MODE_LIGHTSOURCE\n"
2936 "float3 CubeVector : TEXCOORD3,\n"
2938 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2939 "float4 ModelViewPosition : TEXCOORD0,\n"
2941 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2942 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2943 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2944 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2946 "#ifdef USESHADOWMAPORTHO\n"
2947 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2950 "uniform sampler Texture_Normal : register(s0),\n"
2951 "uniform sampler Texture_Color : register(s1),\n"
2952 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2953 "uniform sampler Texture_Gloss : register(s2),\n"
2956 "uniform sampler Texture_Glow : register(s3),\n"
2958 "#ifdef USEVERTEXTEXTUREBLEND\n"
2959 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2960 "uniform sampler Texture_SecondaryColor : register(s5),\n"
2961 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2962 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2965 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
2968 "#ifdef USECOLORMAPPING\n"
2969 "uniform sampler Texture_Pants : register(s4),\n"
2970 "uniform sampler Texture_Shirt : register(s7),\n"
2973 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
2974 "uniform sampler Texture_FogMask : register(s8),\n"
2976 "#ifdef USELIGHTMAP\n"
2977 "uniform sampler Texture_Lightmap : register(s9),\n"
2979 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2980 "uniform sampler Texture_Deluxemap : register(s10),\n"
2982 "#ifdef USEREFLECTION\n"
2983 "uniform sampler Texture_Reflection : register(s7),\n"
2986 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2987 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2988 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2990 "#ifdef USEDEFERREDLIGHTMAP\n"
2991 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2992 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2993 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
2994 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
2997 "#ifdef USECOLORMAPPING\n"
2998 "uniform half3 Color_Pants : register(c7),\n"
2999 "uniform half3 Color_Shirt : register(c8),\n"
3002 "uniform float3 FogColor : register(c16),\n"
3003 "uniform float FogRangeRecip : register(c20),\n"
3004 "uniform float FogPlaneViewDist : register(c19),\n"
3005 "uniform float FogHeightFade : register(c17),\n"
3008 "#ifdef USEOFFSETMAPPING\n"
3009 "uniform float OffsetMapping_Scale : register(c24),\n"
3012 "#ifdef USEDEFERREDLIGHTMAP\n"
3013 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
3014 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
3015 "uniform half3 DeferredMod_Specular : register(c13),\n"
3017 "uniform half3 Color_Ambient : register(c3),\n"
3018 "uniform half3 Color_Diffuse : register(c4),\n"
3019 "uniform half3 Color_Specular : register(c5),\n"
3020 "uniform half SpecularPower : register(c36),\n"
3022 "uniform half3 Color_Glow : register(c6),\n"
3024 "uniform half Alpha : register(c0),\n"
3025 "#ifdef USEREFLECTION\n"
3026 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3027 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3028 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3029 "uniform half4 ReflectColor : register(c26),\n"
3031 "#ifdef USEREFLECTCUBE\n"
3032 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3033 "uniform sampler Texture_ReflectMask : register(s5),\n"
3034 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3036 "#ifdef MODE_LIGHTDIRECTION\n"
3037 "uniform half3 LightColor : register(c21),\n"
3039 "#ifdef MODE_LIGHTSOURCE\n"
3040 "uniform half3 LightColor : register(c21),\n"
3043 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3044 "uniform sampler Texture_Attenuation : register(s9),\n"
3045 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3048 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3050 "#ifdef USESHADOWMAP2D\n"
3051 "# ifdef USESHADOWSAMPLER\n"
3052 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3054 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3058 "#ifdef USESHADOWMAPVSDCT\n"
3059 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3062 "#if defined(USESHADOWMAP2D)\n"
3063 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3064 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3066 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3068 "out float4 gl_FragColor : COLOR\n"
3071 " float2 TexCoord = TexCoordBoth.xy;\n"
3072 "#ifdef USEVERTEXTEXTUREBLEND\n"
3073 " float2 TexCoord2 = TexCoordBoth.zw;\n"
3075 "#ifdef USEOFFSETMAPPING\n"
3076 " // apply offsetmapping\n"
3077 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3078 "#define TexCoord TexCoordOffset\n"
3081 " // combine the diffuse textures (base, pants, shirt)\n"
3082 " half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3083 "#ifdef USEALPHAKILL\n"
3084 " if (color.a < 0.5)\n"
3087 " color.a *= Alpha;\n"
3088 "#ifdef USECOLORMAPPING\n"
3089 " color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3091 "#ifdef USEVERTEXTEXTUREBLEND\n"
3092 " half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3093 " //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3094 " //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3095 " color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3097 " //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3100 " // get the surface normal\n"
3101 "#ifdef USEVERTEXTEXTUREBLEND\n"
3102 " half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3104 " half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3107 " // get the material colors\n"
3108 " half3 diffusetex = color.rgb;\n"
3109 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3110 "# ifdef USEVERTEXTEXTUREBLEND\n"
3111 " half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3113 " half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3117 "#ifdef USEREFLECTCUBE\n"
3118 " float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3119 " float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3120 " float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3121 " diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3127 "#ifdef MODE_LIGHTSOURCE\n"
3128 " // light source\n"
3129 "#ifdef USEDIFFUSE\n"
3130 " half3 lightnormal = half3(normalize(LightVector));\n"
3131 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3132 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3133 "#ifdef USESPECULAR\n"
3134 "#ifdef USEEXACTSPECULARMATH\n"
3135 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3137 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3138 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3140 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3143 " color.rgb = diffusetex * Color_Ambient;\n"
3145 " color.rgb *= LightColor;\n"
3146 " color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3147 "#if defined(USESHADOWMAP2D)\n"
3148 " color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3149 "#ifdef USESHADOWMAPVSDCT\n"
3150 ", Texture_CubeProjection\n"
3155 "# ifdef USECUBEFILTER\n"
3156 " color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3159 "#ifdef USESHADOWMAP2D\n"
3160 "#ifdef USESHADOWMAPVSDCT\n"
3161 "// float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3163 "// float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3165 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3166 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3167 "// color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3168 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3169 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3170 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3171 "// color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3172 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3173 "// color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3174 "// color.r = half(shadowmaptc.z);\n"
3175 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3176 "// color.r = half(shadowmaptc.z);\n"
3178 "// color.rgb = abs(CubeVector);\n"
3180 "// color.rgb = half3(1,1,1);\n"
3181 "#endif // MODE_LIGHTSOURCE\n"
3186 "#ifdef MODE_LIGHTDIRECTION\n"
3188 "#ifdef USEDIFFUSE\n"
3189 " half3 lightnormal = half3(normalize(LightVector));\n"
3191 "#define lightcolor LightColor\n"
3192 "#endif // MODE_LIGHTDIRECTION\n"
3193 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3195 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3196 " half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3197 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3198 " // convert modelspace light vector to tangentspace\n"
3199 " half3 lightnormal;\n"
3200 " lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3201 " lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3202 " lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3203 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3204 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3205 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3206 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3207 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3208 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3209 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3210 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3211 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3212 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3213 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3214 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3216 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3217 " half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3218 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3224 "#ifdef MODE_FAKELIGHT\n"
3226 "half3 lightnormal = half3(normalize(EyeVector));\n"
3227 "half3 lightcolor = half3(1.0,1.0,1.0);\n"
3228 "#endif // MODE_FAKELIGHT\n"
3233 "#ifdef MODE_LIGHTMAP\n"
3234 " color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3235 "#endif // MODE_LIGHTMAP\n"
3236 "#ifdef MODE_VERTEXCOLOR\n"
3237 " color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3238 "#endif // MODE_VERTEXCOLOR\n"
3239 "#ifdef MODE_FLATCOLOR\n"
3240 " color.rgb = diffusetex * Color_Ambient;\n"
3241 "#endif // MODE_FLATCOLOR\n"
3247 "# ifdef USEDIFFUSE\n"
3248 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3249 "# ifdef USESPECULAR\n"
3250 "# ifdef USEEXACTSPECULARMATH\n"
3251 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3253 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3254 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3256 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3258 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3261 " color.rgb = diffusetex * Color_Ambient;\n"
3265 "#ifdef USESHADOWMAPORTHO\n"
3266 " color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
3269 "#ifdef USEDEFERREDLIGHTMAP\n"
3270 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3271 " color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3272 " color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3273 "// color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
3274 "// color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
3278 "#ifdef USEVERTEXTEXTUREBLEND\n"
3279 " color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3281 " color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3286 " color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3289 " // 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"
3290 "#ifdef USEREFLECTION\n"
3291 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3292 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3293 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3294 " float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3295 " // FIXME temporary hack to detect the case that the reflection\n"
3296 " // gets blackened at edges due to leaving the area that contains actual\n"
3298 " // Remove this 'ack once we have a better way to stop this thing from\n"
3300 " float 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 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3304 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3305 " color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3308 " gl_FragColor = float4(color);\n"
3310 "#endif // FRAGMENT_SHADER\n"
3312 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3313 "#endif // !MODE_DEFERREDGEOMETRY\n"
3314 "#endif // !MODE_WATER\n"
3315 "#endif // !MODE_REFRACTION\n"
3316 "#endif // !MODE_BLOOMBLUR\n"
3317 "#endif // !MODE_GENERIC\n"
3318 "#endif // !MODE_POSTPROCESS\n"
3319 "#endif // !MODE_SHOWDEPTH\n"
3320 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3323 char *glslshaderstring = NULL;
3324 char *cgshaderstring = NULL;
3325 char *hlslshaderstring = NULL;
3327 //=======================================================================================================================================================
3329 typedef struct shaderpermutationinfo_s
3331 const char *pretext;
3334 shaderpermutationinfo_t;
3336 typedef struct shadermodeinfo_s
3338 const char *vertexfilename;
3339 const char *geometryfilename;
3340 const char *fragmentfilename;
3341 const char *pretext;
3346 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3347 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3349 {"#define USEDIFFUSE\n", " diffuse"},
3350 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3351 {"#define USEVIEWTINT\n", " viewtint"},
3352 {"#define USECOLORMAPPING\n", " colormapping"},
3353 {"#define USESATURATION\n", " saturation"},
3354 {"#define USEFOGINSIDE\n", " foginside"},
3355 {"#define USEFOGOUTSIDE\n", " fogoutside"},
3356 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3357 {"#define USEGAMMARAMPS\n", " gammaramps"},
3358 {"#define USECUBEFILTER\n", " cubefilter"},
3359 {"#define USEGLOW\n", " glow"},
3360 {"#define USEBLOOM\n", " bloom"},
3361 {"#define USESPECULAR\n", " specular"},
3362 {"#define USEPOSTPROCESSING\n", " postprocessing"},
3363 {"#define USEREFLECTION\n", " reflection"},
3364 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3365 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3366 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3367 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3368 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3369 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3370 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3371 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3372 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3373 {"#define USEALPHAKILL\n", " alphakill"},
3374 {"#define USEREFLECTCUBE\n", " reflectcube"},
3375 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
3378 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3379 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3381 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3382 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3383 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3384 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3385 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3386 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3387 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3388 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3389 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3390 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3391 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3392 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3393 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3394 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3395 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3396 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3400 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3402 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3403 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3404 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3405 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3406 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3407 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3408 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FAKELIGHT\n", " fakelight"},
3409 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3410 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3411 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3412 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3413 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3414 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3415 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3416 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3417 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3422 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3424 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3425 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3426 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3427 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3428 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3429 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3430 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3431 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3432 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3433 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3434 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3435 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3436 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3437 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3438 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3439 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3443 struct r_glsl_permutation_s;
3444 typedef struct r_glsl_permutation_s
3446 /// hash lookup data
3447 struct r_glsl_permutation_s *hashnext;
3449 unsigned int permutation;
3451 /// indicates if we have tried compiling this permutation already
3453 /// 0 if compilation failed
3455 /// locations of detected uniforms in program object, or -1 if not found
3456 int loc_Texture_First;
3457 int loc_Texture_Second;
3458 int loc_Texture_GammaRamps;
3459 int loc_Texture_Normal;
3460 int loc_Texture_Color;
3461 int loc_Texture_Gloss;
3462 int loc_Texture_Glow;
3463 int loc_Texture_SecondaryNormal;
3464 int loc_Texture_SecondaryColor;
3465 int loc_Texture_SecondaryGloss;
3466 int loc_Texture_SecondaryGlow;
3467 int loc_Texture_Pants;
3468 int loc_Texture_Shirt;
3469 int loc_Texture_FogHeightTexture;
3470 int loc_Texture_FogMask;
3471 int loc_Texture_Lightmap;
3472 int loc_Texture_Deluxemap;
3473 int loc_Texture_Attenuation;
3474 int loc_Texture_Cube;
3475 int loc_Texture_Refraction;
3476 int loc_Texture_Reflection;
3477 int loc_Texture_ShadowMap2D;
3478 int loc_Texture_CubeProjection;
3479 int loc_Texture_ScreenDepth;
3480 int loc_Texture_ScreenNormalMap;
3481 int loc_Texture_ScreenDiffuse;
3482 int loc_Texture_ScreenSpecular;
3483 int loc_Texture_ReflectMask;
3484 int loc_Texture_ReflectCube;
3486 int loc_BloomBlur_Parameters;
3488 int loc_Color_Ambient;
3489 int loc_Color_Diffuse;
3490 int loc_Color_Specular;
3492 int loc_Color_Pants;
3493 int loc_Color_Shirt;
3494 int loc_DeferredColor_Ambient;
3495 int loc_DeferredColor_Diffuse;
3496 int loc_DeferredColor_Specular;
3497 int loc_DeferredMod_Diffuse;
3498 int loc_DeferredMod_Specular;
3499 int loc_DistortScaleRefractReflect;
3500 int loc_EyePosition;
3502 int loc_FogHeightFade;
3504 int loc_FogPlaneViewDist;
3505 int loc_FogRangeRecip;
3508 int loc_LightPosition;
3509 int loc_OffsetMapping_Scale;
3511 int loc_ReflectColor;
3512 int loc_ReflectFactor;
3513 int loc_ReflectOffset;
3514 int loc_RefractColor;
3516 int loc_ScreenCenterRefractReflect;
3517 int loc_ScreenScaleRefractReflect;
3518 int loc_ScreenToDepth;
3519 int loc_ShadowMap_Parameters;
3520 int loc_ShadowMap_TextureScale;
3521 int loc_SpecularPower;
3526 int loc_ViewTintColor;
3527 int loc_ViewToLight;
3528 int loc_ModelToLight;
3530 int loc_BackgroundTexMatrix;
3531 int loc_ModelViewProjectionMatrix;
3532 int loc_ModelViewMatrix;
3533 int loc_PixelToScreenTexCoord;
3534 int loc_ModelToReflectCube;
3535 int loc_ShadowMapMatrix;
3536 int loc_BloomColorSubtract;
3537 int loc_NormalmapScrollBlend;
3539 r_glsl_permutation_t;
3541 #define SHADERPERMUTATION_HASHSIZE 256
3544 // non-degradable "lightweight" shader parameters to keep the permutations simpler
3545 // these can NOT degrade! only use for simple stuff
3548 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
3549 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3550 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
3551 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
3552 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
3553 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5 ///< postprocess uservec4 is enabled
3555 #define SHADERSTATICPARMS_COUNT 6
3557 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
3558 static int shaderstaticparms_count = 0;
3560 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
3561 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
3562 qboolean R_CompileShader_CheckStaticParms(void)
3564 static int r_compileshader_staticparms_save[1];
3565 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
3566 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
3569 if (r_glsl_saturation_redcompensate.integer)
3570 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
3571 if (r_shadow_glossexact.integer)
3572 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
3573 if (r_glsl_postprocess.integer)
3575 if (r_glsl_postprocess_uservec1_enable.integer)
3576 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
3577 if (r_glsl_postprocess_uservec2_enable.integer)
3578 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
3579 if (r_glsl_postprocess_uservec3_enable.integer)
3580 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
3581 if (r_glsl_postprocess_uservec4_enable.integer)
3582 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
3584 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
3587 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
3588 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
3589 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
3591 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
3592 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
3594 shaderstaticparms_count = 0;
3597 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
3598 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
3599 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
3600 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
3601 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
3602 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
3605 /// information about each possible shader permutation
3606 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3607 /// currently selected permutation
3608 r_glsl_permutation_t *r_glsl_permutation;
3609 /// storage for permutations linked in the hash table
3610 memexpandablearray_t r_glsl_permutationarray;
3612 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3614 //unsigned int hashdepth = 0;
3615 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3616 r_glsl_permutation_t *p;
3617 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3619 if (p->mode == mode && p->permutation == permutation)
3621 //if (hashdepth > 10)
3622 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3627 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3629 p->permutation = permutation;
3630 p->hashnext = r_glsl_permutationhash[mode][hashindex];
3631 r_glsl_permutationhash[mode][hashindex] = p;
3632 //if (hashdepth > 10)
3633 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3637 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3640 if (!filename || !filename[0])
3642 if (!strcmp(filename, "glsl/default.glsl"))
3644 if (!glslshaderstring)
3646 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3647 if (glslshaderstring)
3648 Con_DPrintf("Loading shaders from file %s...\n", filename);
3650 glslshaderstring = (char *)builtinshaderstring;
3652 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3653 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3654 return shaderstring;
3656 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3659 if (printfromdisknotice)
3660 Con_DPrintf("from disk %s... ", filename);
3661 return shaderstring;
3663 return shaderstring;
3666 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3669 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3670 char *vertexstring, *geometrystring, *fragmentstring;
3671 char permutationname[256];
3672 int vertstrings_count = 0;
3673 int geomstrings_count = 0;
3674 int fragstrings_count = 0;
3675 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3676 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3677 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3684 permutationname[0] = 0;
3685 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
3686 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3687 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3689 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3691 // the first pretext is which type of shader to compile as
3692 // (later these will all be bound together as a program object)
3693 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3694 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3695 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3697 // the second pretext is the mode (for example a light source)
3698 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3699 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3700 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3701 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3703 // now add all the permutation pretexts
3704 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3706 if (permutation & (1<<i))
3708 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3709 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3710 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3711 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3715 // keep line numbers correct
3716 vertstrings_list[vertstrings_count++] = "\n";
3717 geomstrings_list[geomstrings_count++] = "\n";
3718 fragstrings_list[fragstrings_count++] = "\n";
3723 R_CompileShader_AddStaticParms(mode, permutation);
3724 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3725 vertstrings_count += shaderstaticparms_count;
3726 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3727 geomstrings_count += shaderstaticparms_count;
3728 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3729 fragstrings_count += shaderstaticparms_count;
3731 // now append the shader text itself
3732 vertstrings_list[vertstrings_count++] = vertexstring;
3733 geomstrings_list[geomstrings_count++] = geometrystring;
3734 fragstrings_list[fragstrings_count++] = fragmentstring;
3736 // if any sources were NULL, clear the respective list
3738 vertstrings_count = 0;
3739 if (!geometrystring)
3740 geomstrings_count = 0;
3741 if (!fragmentstring)
3742 fragstrings_count = 0;
3744 // compile the shader program
3745 if (vertstrings_count + geomstrings_count + fragstrings_count)
3746 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3750 qglUseProgramObjectARB(p->program);CHECKGLERROR
3751 // look up all the uniform variable names we care about, so we don't
3752 // have to look them up every time we set them
3754 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
3755 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
3756 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3757 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
3758 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
3759 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3760 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
3761 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3762 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3763 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3764 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3765 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
3766 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3767 p->loc_Texture_FogHeightTexture = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3768 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3769 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3770 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3771 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3772 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
3773 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3774 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3775 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3776 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3777 p->loc_Texture_ScreenDepth = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3778 p->loc_Texture_ScreenNormalMap = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3779 p->loc_Texture_ScreenDiffuse = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3780 p->loc_Texture_ScreenSpecular = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3781 p->loc_Texture_ReflectMask = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3782 p->loc_Texture_ReflectCube = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3783 p->loc_Alpha = qglGetUniformLocationARB(p->program, "Alpha");
3784 p->loc_BloomBlur_Parameters = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3785 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
3786 p->loc_Color_Ambient = qglGetUniformLocationARB(p->program, "Color_Ambient");
3787 p->loc_Color_Diffuse = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3788 p->loc_Color_Specular = qglGetUniformLocationARB(p->program, "Color_Specular");
3789 p->loc_Color_Glow = qglGetUniformLocationARB(p->program, "Color_Glow");
3790 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
3791 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
3792 p->loc_DeferredColor_Ambient = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3793 p->loc_DeferredColor_Diffuse = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3794 p->loc_DeferredColor_Specular = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3795 p->loc_DeferredMod_Diffuse = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3796 p->loc_DeferredMod_Specular = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3797 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3798 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
3799 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
3800 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
3801 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
3802 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3803 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3804 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
3805 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
3806 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
3807 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3808 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
3809 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
3810 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
3811 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
3812 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
3813 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
3814 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3815 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3816 p->loc_ScreenToDepth = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3817 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3818 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3819 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
3820 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
3821 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
3822 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
3823 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
3824 p->loc_ViewTintColor = qglGetUniformLocationARB(p->program, "ViewTintColor");
3825 p->loc_ViewToLight = qglGetUniformLocationARB(p->program, "ViewToLight");
3826 p->loc_ModelToLight = qglGetUniformLocationARB(p->program, "ModelToLight");
3827 p->loc_TexMatrix = qglGetUniformLocationARB(p->program, "TexMatrix");
3828 p->loc_BackgroundTexMatrix = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3829 p->loc_ModelViewMatrix = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3830 p->loc_ModelViewProjectionMatrix = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3831 p->loc_PixelToScreenTexCoord = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3832 p->loc_ModelToReflectCube = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3833 p->loc_ShadowMapMatrix = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3834 p->loc_BloomColorSubtract = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
3835 p->loc_NormalmapScrollBlend = qglGetUniformLocationARB(p->program, "NormalmapScrollBlend");
3836 // initialize the samplers to refer to the texture units we use
3837 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
3838 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
3839 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
3840 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
3841 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
3842 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
3843 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
3844 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3845 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3846 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3847 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
3848 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
3849 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
3850 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3851 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
3852 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
3853 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
3854 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
3855 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
3856 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
3857 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
3858 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
3859 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3860 if (p->loc_Texture_ScreenDepth >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth , GL20TU_SCREENDEPTH);
3861 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3862 if (p->loc_Texture_ScreenDiffuse >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse , GL20TU_SCREENDIFFUSE);
3863 if (p->loc_Texture_ScreenSpecular >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3864 if (p->loc_Texture_ReflectMask >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask , GL20TU_REFLECTMASK);
3865 if (p->loc_Texture_ReflectCube >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube , GL20TU_REFLECTCUBE);
3867 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3870 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
3874 Mem_Free(vertexstring);
3876 Mem_Free(geometrystring);
3878 Mem_Free(fragmentstring);
3881 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3883 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3884 if (r_glsl_permutation != perm)
3886 r_glsl_permutation = perm;
3887 if (!r_glsl_permutation->program)
3889 if (!r_glsl_permutation->compiled)
3890 R_GLSL_CompilePermutation(perm, mode, permutation);
3891 if (!r_glsl_permutation->program)
3893 // remove features until we find a valid permutation
3895 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3897 // reduce i more quickly whenever it would not remove any bits
3898 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3899 if (!(permutation & j))
3902 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3903 if (!r_glsl_permutation->compiled)
3904 R_GLSL_CompilePermutation(perm, mode, permutation);
3905 if (r_glsl_permutation->program)
3908 if (i >= SHADERPERMUTATION_COUNT)
3910 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3911 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3912 qglUseProgramObjectARB(0);CHECKGLERROR
3913 return; // no bit left to clear, entire mode is broken
3918 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3920 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3921 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3922 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3926 #include <Cg/cgGL.h>
3927 struct r_cg_permutation_s;
3928 typedef struct r_cg_permutation_s
3930 /// hash lookup data
3931 struct r_cg_permutation_s *hashnext;
3933 unsigned int permutation;
3935 /// indicates if we have tried compiling this permutation already
3937 /// 0 if compilation failed
3940 /// locations of detected parameters in programs, or NULL if not found
3941 CGparameter vp_EyePosition;
3942 CGparameter vp_FogPlane;
3943 CGparameter vp_LightDir;
3944 CGparameter vp_LightPosition;
3945 CGparameter vp_ModelToLight;
3946 CGparameter vp_TexMatrix;
3947 CGparameter vp_BackgroundTexMatrix;
3948 CGparameter vp_ModelViewProjectionMatrix;
3949 CGparameter vp_ModelViewMatrix;
3950 CGparameter vp_ShadowMapMatrix;
3952 CGparameter fp_Texture_First;
3953 CGparameter fp_Texture_Second;
3954 CGparameter fp_Texture_GammaRamps;
3955 CGparameter fp_Texture_Normal;
3956 CGparameter fp_Texture_Color;
3957 CGparameter fp_Texture_Gloss;
3958 CGparameter fp_Texture_Glow;
3959 CGparameter fp_Texture_SecondaryNormal;
3960 CGparameter fp_Texture_SecondaryColor;
3961 CGparameter fp_Texture_SecondaryGloss;
3962 CGparameter fp_Texture_SecondaryGlow;
3963 CGparameter fp_Texture_Pants;
3964 CGparameter fp_Texture_Shirt;
3965 CGparameter fp_Texture_FogHeightTexture;
3966 CGparameter fp_Texture_FogMask;
3967 CGparameter fp_Texture_Lightmap;
3968 CGparameter fp_Texture_Deluxemap;
3969 CGparameter fp_Texture_Attenuation;
3970 CGparameter fp_Texture_Cube;
3971 CGparameter fp_Texture_Refraction;
3972 CGparameter fp_Texture_Reflection;
3973 CGparameter fp_Texture_ShadowMap2D;
3974 CGparameter fp_Texture_CubeProjection;
3975 CGparameter fp_Texture_ScreenDepth;
3976 CGparameter fp_Texture_ScreenNormalMap;
3977 CGparameter fp_Texture_ScreenDiffuse;
3978 CGparameter fp_Texture_ScreenSpecular;
3979 CGparameter fp_Texture_ReflectMask;
3980 CGparameter fp_Texture_ReflectCube;
3981 CGparameter fp_Alpha;
3982 CGparameter fp_BloomBlur_Parameters;
3983 CGparameter fp_ClientTime;
3984 CGparameter fp_Color_Ambient;
3985 CGparameter fp_Color_Diffuse;
3986 CGparameter fp_Color_Specular;
3987 CGparameter fp_Color_Glow;
3988 CGparameter fp_Color_Pants;
3989 CGparameter fp_Color_Shirt;
3990 CGparameter fp_DeferredColor_Ambient;
3991 CGparameter fp_DeferredColor_Diffuse;
3992 CGparameter fp_DeferredColor_Specular;
3993 CGparameter fp_DeferredMod_Diffuse;
3994 CGparameter fp_DeferredMod_Specular;
3995 CGparameter fp_DistortScaleRefractReflect;
3996 CGparameter fp_EyePosition;
3997 CGparameter fp_FogColor;
3998 CGparameter fp_FogHeightFade;
3999 CGparameter fp_FogPlane;
4000 CGparameter fp_FogPlaneViewDist;
4001 CGparameter fp_FogRangeRecip;
4002 CGparameter fp_LightColor;
4003 CGparameter fp_LightDir;
4004 CGparameter fp_LightPosition;
4005 CGparameter fp_OffsetMapping_Scale;
4006 CGparameter fp_PixelSize;
4007 CGparameter fp_ReflectColor;
4008 CGparameter fp_ReflectFactor;
4009 CGparameter fp_ReflectOffset;
4010 CGparameter fp_RefractColor;
4011 CGparameter fp_Saturation;
4012 CGparameter fp_ScreenCenterRefractReflect;
4013 CGparameter fp_ScreenScaleRefractReflect;
4014 CGparameter fp_ScreenToDepth;
4015 CGparameter fp_ShadowMap_Parameters;
4016 CGparameter fp_ShadowMap_TextureScale;
4017 CGparameter fp_SpecularPower;
4018 CGparameter fp_UserVec1;
4019 CGparameter fp_UserVec2;
4020 CGparameter fp_UserVec3;
4021 CGparameter fp_UserVec4;
4022 CGparameter fp_ViewTintColor;
4023 CGparameter fp_ViewToLight;
4024 CGparameter fp_PixelToScreenTexCoord;
4025 CGparameter fp_ModelToReflectCube;
4026 CGparameter fp_BloomColorSubtract;
4027 CGparameter fp_NormalmapScrollBlend;
4031 /// information about each possible shader permutation
4032 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4033 /// currently selected permutation
4034 r_cg_permutation_t *r_cg_permutation;
4035 /// storage for permutations linked in the hash table
4036 memexpandablearray_t r_cg_permutationarray;
4038 #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));}}
4040 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
4042 //unsigned int hashdepth = 0;
4043 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4044 r_cg_permutation_t *p;
4045 for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4047 if (p->mode == mode && p->permutation == permutation)
4049 //if (hashdepth > 10)
4050 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4055 p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4057 p->permutation = permutation;
4058 p->hashnext = r_cg_permutationhash[mode][hashindex];
4059 r_cg_permutationhash[mode][hashindex] = p;
4060 //if (hashdepth > 10)
4061 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4065 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4068 if (!filename || !filename[0])
4070 if (!strcmp(filename, "cg/default.cg"))
4072 if (!cgshaderstring)
4074 cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4076 Con_DPrintf("Loading shaders from file %s...\n", filename);
4078 cgshaderstring = (char *)builtincgshaderstring;
4080 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4081 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4082 return shaderstring;
4084 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4087 if (printfromdisknotice)
4088 Con_DPrintf("from disk %s... ", filename);
4089 return shaderstring;
4091 return shaderstring;
4094 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4096 // TODO: load or create .fp and .vp shader files
4099 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4102 shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4103 int vertstring_length = 0;
4104 int geomstring_length = 0;
4105 int fragstring_length = 0;
4107 char *vertexstring, *geometrystring, *fragmentstring;
4108 char *vertstring, *geomstring, *fragstring;
4109 char permutationname[256];
4110 char cachename[256];
4111 CGprofile vertexProfile;
4112 CGprofile fragmentProfile;
4113 int vertstrings_count = 0;
4114 int geomstrings_count = 0;
4115 int fragstrings_count = 0;
4116 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4117 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4118 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4126 permutationname[0] = 0;
4128 vertexstring = R_CG_GetText(modeinfo->vertexfilename, true);
4129 geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4130 fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4132 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4133 strlcat(cachename, "cg/", sizeof(cachename));
4135 // the first pretext is which type of shader to compile as
4136 // (later these will all be bound together as a program object)
4137 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4138 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4139 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4141 // the second pretext is the mode (for example a light source)
4142 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4143 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4144 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4145 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4146 strlcat(cachename, modeinfo->name, sizeof(cachename));
4148 // now add all the permutation pretexts
4149 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4151 if (permutation & (1<<i))
4153 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4154 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4155 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4156 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4157 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4161 // keep line numbers correct
4162 vertstrings_list[vertstrings_count++] = "\n";
4163 geomstrings_list[geomstrings_count++] = "\n";
4164 fragstrings_list[fragstrings_count++] = "\n";
4169 R_CompileShader_AddStaticParms(mode, permutation);
4170 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4171 vertstrings_count += shaderstaticparms_count;
4172 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4173 geomstrings_count += shaderstaticparms_count;
4174 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4175 fragstrings_count += shaderstaticparms_count;
4177 // replace spaces in the cachename with _ characters
4178 for (i = 0;cachename[i];i++)
4179 if (cachename[i] == ' ')
4182 // now append the shader text itself
4183 vertstrings_list[vertstrings_count++] = vertexstring;
4184 geomstrings_list[geomstrings_count++] = geometrystring;
4185 fragstrings_list[fragstrings_count++] = fragmentstring;
4187 // if any sources were NULL, clear the respective list
4189 vertstrings_count = 0;
4190 if (!geometrystring)
4191 geomstrings_count = 0;
4192 if (!fragmentstring)
4193 fragstrings_count = 0;
4195 vertstring_length = 0;
4196 for (i = 0;i < vertstrings_count;i++)
4197 vertstring_length += strlen(vertstrings_list[i]);
4198 vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4199 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4200 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4202 geomstring_length = 0;
4203 for (i = 0;i < geomstrings_count;i++)
4204 geomstring_length += strlen(geomstrings_list[i]);
4205 geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4206 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4207 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4209 fragstring_length = 0;
4210 for (i = 0;i < fragstrings_count;i++)
4211 fragstring_length += strlen(fragstrings_list[i]);
4212 fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4213 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4214 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4218 //vertexProfile = CG_PROFILE_ARBVP1;
4219 //fragmentProfile = CG_PROFILE_ARBFP1;
4220 vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4221 fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4222 //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4223 //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4224 //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4227 // try to load the cached shader, or generate one
4228 R_CG_CacheShader(p, cachename, vertstring, fragstring);
4230 // if caching failed, do a dynamic compile for now
4232 if (vertstring[0] && !p->vprogram)
4233 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4235 if (fragstring[0] && !p->fprogram)
4236 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4239 // look up all the uniform variable names we care about, so we don't
4240 // have to look them up every time we set them
4244 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4245 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4246 p->vp_EyePosition = cgGetNamedParameter(p->vprogram, "EyePosition");
4247 p->vp_FogPlane = cgGetNamedParameter(p->vprogram, "FogPlane");
4248 p->vp_LightDir = cgGetNamedParameter(p->vprogram, "LightDir");
4249 p->vp_LightPosition = cgGetNamedParameter(p->vprogram, "LightPosition");
4250 p->vp_ModelToLight = cgGetNamedParameter(p->vprogram, "ModelToLight");
4251 p->vp_TexMatrix = cgGetNamedParameter(p->vprogram, "TexMatrix");
4252 p->vp_BackgroundTexMatrix = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4253 p->vp_ModelViewProjectionMatrix = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4254 p->vp_ModelViewMatrix = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4255 p->vp_ShadowMapMatrix = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4261 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4262 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4263 p->fp_Texture_First = cgGetNamedParameter(p->fprogram, "Texture_First");
4264 p->fp_Texture_Second = cgGetNamedParameter(p->fprogram, "Texture_Second");
4265 p->fp_Texture_GammaRamps = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4266 p->fp_Texture_Normal = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4267 p->fp_Texture_Color = cgGetNamedParameter(p->fprogram, "Texture_Color");
4268 p->fp_Texture_Gloss = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4269 p->fp_Texture_Glow = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4270 p->fp_Texture_SecondaryNormal = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4271 p->fp_Texture_SecondaryColor = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4272 p->fp_Texture_SecondaryGloss = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4273 p->fp_Texture_SecondaryGlow = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4274 p->fp_Texture_Pants = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4275 p->fp_Texture_Shirt = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4276 p->fp_Texture_FogHeightTexture = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4277 p->fp_Texture_FogMask = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4278 p->fp_Texture_Lightmap = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4279 p->fp_Texture_Deluxemap = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4280 p->fp_Texture_Attenuation = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4281 p->fp_Texture_Cube = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4282 p->fp_Texture_Refraction = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4283 p->fp_Texture_Reflection = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4284 p->fp_Texture_ShadowMap2D = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4285 p->fp_Texture_CubeProjection = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4286 p->fp_Texture_ScreenDepth = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4287 p->fp_Texture_ScreenNormalMap = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4288 p->fp_Texture_ScreenDiffuse = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4289 p->fp_Texture_ScreenSpecular = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4290 p->fp_Texture_ReflectMask = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4291 p->fp_Texture_ReflectCube = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4292 p->fp_Alpha = cgGetNamedParameter(p->fprogram, "Alpha");
4293 p->fp_BloomBlur_Parameters = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4294 p->fp_ClientTime = cgGetNamedParameter(p->fprogram, "ClientTime");
4295 p->fp_Color_Ambient = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4296 p->fp_Color_Diffuse = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4297 p->fp_Color_Specular = cgGetNamedParameter(p->fprogram, "Color_Specular");
4298 p->fp_Color_Glow = cgGetNamedParameter(p->fprogram, "Color_Glow");
4299 p->fp_Color_Pants = cgGetNamedParameter(p->fprogram, "Color_Pants");
4300 p->fp_Color_Shirt = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4301 p->fp_DeferredColor_Ambient = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4302 p->fp_DeferredColor_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4303 p->fp_DeferredColor_Specular = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4304 p->fp_DeferredMod_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4305 p->fp_DeferredMod_Specular = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4306 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4307 p->fp_EyePosition = cgGetNamedParameter(p->fprogram, "EyePosition");
4308 p->fp_FogColor = cgGetNamedParameter(p->fprogram, "FogColor");
4309 p->fp_FogHeightFade = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4310 p->fp_FogPlane = cgGetNamedParameter(p->fprogram, "FogPlane");
4311 p->fp_FogPlaneViewDist = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4312 p->fp_FogRangeRecip = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4313 p->fp_LightColor = cgGetNamedParameter(p->fprogram, "LightColor");
4314 p->fp_LightDir = cgGetNamedParameter(p->fprogram, "LightDir");
4315 p->fp_LightPosition = cgGetNamedParameter(p->fprogram, "LightPosition");
4316 p->fp_OffsetMapping_Scale = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4317 p->fp_PixelSize = cgGetNamedParameter(p->fprogram, "PixelSize");
4318 p->fp_ReflectColor = cgGetNamedParameter(p->fprogram, "ReflectColor");
4319 p->fp_ReflectFactor = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4320 p->fp_ReflectOffset = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4321 p->fp_RefractColor = cgGetNamedParameter(p->fprogram, "RefractColor");
4322 p->fp_Saturation = cgGetNamedParameter(p->fprogram, "Saturation");
4323 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4324 p->fp_ScreenScaleRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4325 p->fp_ScreenToDepth = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4326 p->fp_ShadowMap_Parameters = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4327 p->fp_ShadowMap_TextureScale = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4328 p->fp_SpecularPower = cgGetNamedParameter(p->fprogram, "SpecularPower");
4329 p->fp_UserVec1 = cgGetNamedParameter(p->fprogram, "UserVec1");
4330 p->fp_UserVec2 = cgGetNamedParameter(p->fprogram, "UserVec2");
4331 p->fp_UserVec3 = cgGetNamedParameter(p->fprogram, "UserVec3");
4332 p->fp_UserVec4 = cgGetNamedParameter(p->fprogram, "UserVec4");
4333 p->fp_ViewTintColor = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4334 p->fp_ViewToLight = cgGetNamedParameter(p->fprogram, "ViewToLight");
4335 p->fp_PixelToScreenTexCoord = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4336 p->fp_ModelToReflectCube = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4337 p->fp_BloomColorSubtract = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4338 p->fp_NormalmapScrollBlend = cgGetNamedParameter(p->fprogram, "NormalmapScrollBlend");
4342 if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4343 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4345 Con_Printf("^1CG shader %s failed! some features may not work properly.\n", permutationname);
4349 Mem_Free(vertstring);
4351 Mem_Free(geomstring);
4353 Mem_Free(fragstring);
4355 Mem_Free(vertexstring);
4357 Mem_Free(geometrystring);
4359 Mem_Free(fragmentstring);
4362 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4364 r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4367 if (r_cg_permutation != perm)
4369 r_cg_permutation = perm;
4370 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4372 if (!r_cg_permutation->compiled)
4373 R_CG_CompilePermutation(perm, mode, permutation);
4374 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4376 // remove features until we find a valid permutation
4378 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4380 // reduce i more quickly whenever it would not remove any bits
4381 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4382 if (!(permutation & j))
4385 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4386 if (!r_cg_permutation->compiled)
4387 R_CG_CompilePermutation(perm, mode, permutation);
4388 if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4391 if (i >= SHADERPERMUTATION_COUNT)
4393 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4394 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4395 return; // no bit left to clear, entire mode is broken
4401 if (r_cg_permutation->vprogram)
4403 cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4404 cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4405 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4409 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4410 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4412 if (r_cg_permutation->fprogram)
4414 cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4415 cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4416 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4420 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4421 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4425 if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4426 if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4427 if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4430 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4432 cgGLSetTextureParameter(param, R_GetTexture(tex));
4433 cgGLEnableTextureParameter(param);
4441 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4442 extern D3DCAPS9 vid_d3d9caps;
4445 struct r_hlsl_permutation_s;
4446 typedef struct r_hlsl_permutation_s
4448 /// hash lookup data
4449 struct r_hlsl_permutation_s *hashnext;
4451 unsigned int permutation;
4453 /// indicates if we have tried compiling this permutation already
4455 /// NULL if compilation failed
4456 IDirect3DVertexShader9 *vertexshader;
4457 IDirect3DPixelShader9 *pixelshader;
4459 r_hlsl_permutation_t;
4461 typedef enum D3DVSREGISTER_e
4463 D3DVSREGISTER_TexMatrix = 0, // float4x4
4464 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4465 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4466 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4467 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4468 D3DVSREGISTER_ModelToLight = 20, // float4x4
4469 D3DVSREGISTER_EyePosition = 24,
4470 D3DVSREGISTER_FogPlane = 25,
4471 D3DVSREGISTER_LightDir = 26,
4472 D3DVSREGISTER_LightPosition = 27,
4476 typedef enum D3DPSREGISTER_e
4478 D3DPSREGISTER_Alpha = 0,
4479 D3DPSREGISTER_BloomBlur_Parameters = 1,
4480 D3DPSREGISTER_ClientTime = 2,
4481 D3DPSREGISTER_Color_Ambient = 3,
4482 D3DPSREGISTER_Color_Diffuse = 4,
4483 D3DPSREGISTER_Color_Specular = 5,
4484 D3DPSREGISTER_Color_Glow = 6,
4485 D3DPSREGISTER_Color_Pants = 7,
4486 D3DPSREGISTER_Color_Shirt = 8,
4487 D3DPSREGISTER_DeferredColor_Ambient = 9,
4488 D3DPSREGISTER_DeferredColor_Diffuse = 10,
4489 D3DPSREGISTER_DeferredColor_Specular = 11,
4490 D3DPSREGISTER_DeferredMod_Diffuse = 12,
4491 D3DPSREGISTER_DeferredMod_Specular = 13,
4492 D3DPSREGISTER_DistortScaleRefractReflect = 14,
4493 D3DPSREGISTER_EyePosition = 15, // unused
4494 D3DPSREGISTER_FogColor = 16,
4495 D3DPSREGISTER_FogHeightFade = 17,
4496 D3DPSREGISTER_FogPlane = 18,
4497 D3DPSREGISTER_FogPlaneViewDist = 19,
4498 D3DPSREGISTER_FogRangeRecip = 20,
4499 D3DPSREGISTER_LightColor = 21,
4500 D3DPSREGISTER_LightDir = 22, // unused
4501 D3DPSREGISTER_LightPosition = 23,
4502 D3DPSREGISTER_OffsetMapping_Scale = 24,
4503 D3DPSREGISTER_PixelSize = 25,
4504 D3DPSREGISTER_ReflectColor = 26,
4505 D3DPSREGISTER_ReflectFactor = 27,
4506 D3DPSREGISTER_ReflectOffset = 28,
4507 D3DPSREGISTER_RefractColor = 29,
4508 D3DPSREGISTER_Saturation = 30,
4509 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4510 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4511 D3DPSREGISTER_ScreenToDepth = 33,
4512 D3DPSREGISTER_ShadowMap_Parameters = 34,
4513 D3DPSREGISTER_ShadowMap_TextureScale = 35,
4514 D3DPSREGISTER_SpecularPower = 36,
4515 D3DPSREGISTER_UserVec1 = 37,
4516 D3DPSREGISTER_UserVec2 = 38,
4517 D3DPSREGISTER_UserVec3 = 39,
4518 D3DPSREGISTER_UserVec4 = 40,
4519 D3DPSREGISTER_ViewTintColor = 41,
4520 D3DPSREGISTER_PixelToScreenTexCoord = 42,
4521 D3DPSREGISTER_BloomColorSubtract = 43,
4522 D3DPSREGISTER_ViewToLight = 44, // float4x4
4523 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4524 D3DPSREGISTER_NormalmapScrollBlend = 52,
4529 /// information about each possible shader permutation
4530 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4531 /// currently selected permutation
4532 r_hlsl_permutation_t *r_hlsl_permutation;
4533 /// storage for permutations linked in the hash table
4534 memexpandablearray_t r_hlsl_permutationarray;
4536 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4538 //unsigned int hashdepth = 0;
4539 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4540 r_hlsl_permutation_t *p;
4541 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4543 if (p->mode == mode && p->permutation == permutation)
4545 //if (hashdepth > 10)
4546 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4551 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4553 p->permutation = permutation;
4554 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4555 r_hlsl_permutationhash[mode][hashindex] = p;
4556 //if (hashdepth > 10)
4557 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4561 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4564 if (!filename || !filename[0])
4566 if (!strcmp(filename, "hlsl/default.hlsl"))
4568 if (!hlslshaderstring)
4570 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4571 if (hlslshaderstring)
4572 Con_DPrintf("Loading shaders from file %s...\n", filename);
4574 hlslshaderstring = (char *)builtincgshaderstring;
4576 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4577 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4578 return shaderstring;
4580 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4583 if (printfromdisknotice)
4584 Con_DPrintf("from disk %s... ", filename);
4585 return shaderstring;
4587 return shaderstring;
4591 //#include <d3dx9shader.h>
4592 //#include <d3dx9mesh.h>
4594 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4596 DWORD *vsbin = NULL;
4597 DWORD *psbin = NULL;
4598 fs_offset_t vsbinsize;
4599 fs_offset_t psbinsize;
4600 // IDirect3DVertexShader9 *vs = NULL;
4601 // IDirect3DPixelShader9 *ps = NULL;
4602 ID3DXBuffer *vslog = NULL;
4603 ID3DXBuffer *vsbuffer = NULL;
4604 ID3DXConstantTable *vsconstanttable = NULL;
4605 ID3DXBuffer *pslog = NULL;
4606 ID3DXBuffer *psbuffer = NULL;
4607 ID3DXConstantTable *psconstanttable = NULL;
4610 char temp[MAX_INPUTLINE];
4611 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4612 qboolean debugshader = gl_paranoid.integer != 0;
4613 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4614 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4617 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4618 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4620 if ((!vsbin && vertstring) || (!psbin && fragstring))
4622 const char* dllnames_d3dx9 [] =
4646 dllhandle_t d3dx9_dll = NULL;
4647 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4648 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4649 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4650 dllfunction_t d3dx9_dllfuncs[] =
4652 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
4653 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
4654 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
4657 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4659 DWORD shaderflags = 0;
4661 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4662 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4663 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4664 if (vertstring && vertstring[0])
4668 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4669 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4670 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4671 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4674 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4677 vsbinsize = vsbuffer->GetBufferSize();
4678 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4679 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4680 vsbuffer->Release();
4684 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4685 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4689 if (fragstring && fragstring[0])
4693 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4694 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4695 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4696 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4699 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4702 psbinsize = psbuffer->GetBufferSize();
4703 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4704 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4705 psbuffer->Release();
4709 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4710 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4714 Sys_UnloadLibrary(&d3dx9_dll);
4717 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4721 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4722 if (FAILED(vsresult))
4723 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4724 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4725 if (FAILED(psresult))
4726 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4728 // free the shader data
4729 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4730 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4733 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4736 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4737 int vertstring_length = 0;
4738 int geomstring_length = 0;
4739 int fragstring_length = 0;
4741 char *vertexstring, *geometrystring, *fragmentstring;
4742 char *vertstring, *geomstring, *fragstring;
4743 char permutationname[256];
4744 char cachename[256];
4745 int vertstrings_count = 0;
4746 int geomstrings_count = 0;
4747 int fragstrings_count = 0;
4748 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4749 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4750 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4755 p->vertexshader = NULL;
4756 p->pixelshader = NULL;
4758 permutationname[0] = 0;
4760 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
4761 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4762 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4764 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4765 strlcat(cachename, "hlsl/", sizeof(cachename));
4767 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4768 vertstrings_count = 0;
4769 geomstrings_count = 0;
4770 fragstrings_count = 0;
4771 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4772 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4773 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4775 // the first pretext is which type of shader to compile as
4776 // (later these will all be bound together as a program object)
4777 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4778 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4779 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4781 // the second pretext is the mode (for example a light source)
4782 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4783 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4784 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4785 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4786 strlcat(cachename, modeinfo->name, sizeof(cachename));
4788 // now add all the permutation pretexts
4789 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4791 if (permutation & (1<<i))
4793 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4794 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4795 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4796 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4797 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4801 // keep line numbers correct
4802 vertstrings_list[vertstrings_count++] = "\n";
4803 geomstrings_list[geomstrings_count++] = "\n";
4804 fragstrings_list[fragstrings_count++] = "\n";
4809 R_CompileShader_AddStaticParms(mode, permutation);
4810 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4811 vertstrings_count += shaderstaticparms_count;
4812 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4813 geomstrings_count += shaderstaticparms_count;
4814 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4815 fragstrings_count += shaderstaticparms_count;
4817 // replace spaces in the cachename with _ characters
4818 for (i = 0;cachename[i];i++)
4819 if (cachename[i] == ' ')
4822 // now append the shader text itself
4823 vertstrings_list[vertstrings_count++] = vertexstring;
4824 geomstrings_list[geomstrings_count++] = geometrystring;
4825 fragstrings_list[fragstrings_count++] = fragmentstring;
4827 // if any sources were NULL, clear the respective list
4829 vertstrings_count = 0;
4830 if (!geometrystring)
4831 geomstrings_count = 0;
4832 if (!fragmentstring)
4833 fragstrings_count = 0;
4835 vertstring_length = 0;
4836 for (i = 0;i < vertstrings_count;i++)
4837 vertstring_length += strlen(vertstrings_list[i]);
4838 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4839 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4840 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4842 geomstring_length = 0;
4843 for (i = 0;i < geomstrings_count;i++)
4844 geomstring_length += strlen(geomstrings_list[i]);
4845 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4846 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4847 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4849 fragstring_length = 0;
4850 for (i = 0;i < fragstrings_count;i++)
4851 fragstring_length += strlen(fragstrings_list[i]);
4852 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4853 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4854 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4856 // try to load the cached shader, or generate one
4857 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4859 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4860 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4862 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
4866 Mem_Free(vertstring);
4868 Mem_Free(geomstring);
4870 Mem_Free(fragstring);
4872 Mem_Free(vertexstring);
4874 Mem_Free(geometrystring);
4876 Mem_Free(fragmentstring);
4879 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4880 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4881 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);}
4882 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);}
4883 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);}
4884 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);}
4886 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4887 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4888 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);}
4889 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);}
4890 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);}
4891 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);}
4893 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4895 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4896 if (r_hlsl_permutation != perm)
4898 r_hlsl_permutation = perm;
4899 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4901 if (!r_hlsl_permutation->compiled)
4902 R_HLSL_CompilePermutation(perm, mode, permutation);
4903 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4905 // remove features until we find a valid permutation
4907 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4909 // reduce i more quickly whenever it would not remove any bits
4910 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4911 if (!(permutation & j))
4914 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4915 if (!r_hlsl_permutation->compiled)
4916 R_HLSL_CompilePermutation(perm, mode, permutation);
4917 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4920 if (i >= SHADERPERMUTATION_COUNT)
4922 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4923 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4924 return; // no bit left to clear, entire mode is broken
4928 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4929 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4931 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4932 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4933 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4937 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
4939 DPSOFTRAST_SetShader(mode, permutation);
4940 DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
4941 DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
4942 DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
4945 void R_GLSL_Restart_f(void)
4947 unsigned int i, limit;
4948 if (glslshaderstring && glslshaderstring != builtinshaderstring)
4949 Mem_Free(glslshaderstring);
4950 glslshaderstring = NULL;
4951 if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4952 Mem_Free(cgshaderstring);
4953 cgshaderstring = NULL;
4954 if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
4955 Mem_Free(hlslshaderstring);
4956 hlslshaderstring = NULL;
4957 switch(vid.renderpath)
4959 case RENDERPATH_D3D9:
4962 r_hlsl_permutation_t *p;
4963 r_hlsl_permutation = NULL;
4964 // cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4965 // cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4966 // cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4967 // cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4968 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
4969 for (i = 0;i < limit;i++)
4971 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
4973 if (p->vertexshader)
4974 IDirect3DVertexShader9_Release(p->vertexshader);
4976 IDirect3DPixelShader9_Release(p->pixelshader);
4977 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
4980 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4984 case RENDERPATH_D3D10:
4985 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4987 case RENDERPATH_D3D11:
4988 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4990 case RENDERPATH_GL20:
4992 r_glsl_permutation_t *p;
4993 r_glsl_permutation = NULL;
4994 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4995 for (i = 0;i < limit;i++)
4997 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4999 GL_Backend_FreeProgram(p->program);
5000 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
5003 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5006 case RENDERPATH_CGGL:
5009 r_cg_permutation_t *p;
5010 r_cg_permutation = NULL;
5011 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5012 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5013 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5014 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5015 limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
5016 for (i = 0;i < limit;i++)
5018 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
5021 cgDestroyProgram(p->vprogram);
5023 cgDestroyProgram(p->fprogram);
5024 Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
5027 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5031 case RENDERPATH_GL13:
5032 case RENDERPATH_GL11:
5034 case RENDERPATH_SOFT:
5039 void R_GLSL_DumpShader_f(void)
5044 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
5047 FS_Print(file, "/* The engine may define the following macros:\n");
5048 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5049 for (i = 0;i < SHADERMODE_COUNT;i++)
5050 FS_Print(file, glslshadermodeinfo[i].pretext);
5051 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5052 FS_Print(file, shaderpermutationinfo[i].pretext);
5053 FS_Print(file, "*/\n");
5054 FS_Print(file, builtinshaderstring);
5056 Con_Printf("glsl/default.glsl written\n");
5059 Con_Printf("failed to write to glsl/default.glsl\n");
5062 file = FS_OpenRealFile("cg/default.cg", "w", false);
5065 FS_Print(file, "/* The engine may define the following macros:\n");
5066 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5067 for (i = 0;i < SHADERMODE_COUNT;i++)
5068 FS_Print(file, cgshadermodeinfo[i].pretext);
5069 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5070 FS_Print(file, shaderpermutationinfo[i].pretext);
5071 FS_Print(file, "*/\n");
5072 FS_Print(file, builtincgshaderstring);
5074 Con_Printf("cg/default.cg written\n");
5077 Con_Printf("failed to write to cg/default.cg\n");
5081 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
5084 FS_Print(file, "/* The engine may define the following macros:\n");
5085 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5086 for (i = 0;i < SHADERMODE_COUNT;i++)
5087 FS_Print(file, hlslshadermodeinfo[i].pretext);
5088 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5089 FS_Print(file, shaderpermutationinfo[i].pretext);
5090 FS_Print(file, "*/\n");
5091 FS_Print(file, builtincgshaderstring);
5093 Con_Printf("hlsl/default.hlsl written\n");
5096 Con_Printf("failed to write to hlsl/default.hlsl\n");
5100 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
5103 texturemode = GL_MODULATE;
5104 switch (vid.renderpath)
5106 case RENDERPATH_D3D9:
5108 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))));
5109 R_Mesh_TexBind(GL20TU_FIRST , first );
5110 R_Mesh_TexBind(GL20TU_SECOND, second);
5113 case RENDERPATH_D3D10:
5114 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5116 case RENDERPATH_D3D11:
5117 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5119 case RENDERPATH_GL20:
5120 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))));
5121 R_Mesh_TexBind(GL20TU_FIRST , first );
5122 R_Mesh_TexBind(GL20TU_SECOND, second);
5124 case RENDERPATH_CGGL:
5127 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))));
5128 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
5129 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
5132 case RENDERPATH_GL13:
5133 R_Mesh_TexBind(0, first );
5134 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
5135 R_Mesh_TexBind(1, second);
5137 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
5139 case RENDERPATH_GL11:
5140 R_Mesh_TexBind(0, first );
5142 case RENDERPATH_SOFT:
5143 R_SetupShader_SetPermutationSoft(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))));
5144 R_Mesh_TexBind(GL20TU_FIRST , first );
5145 R_Mesh_TexBind(GL20TU_SECOND, second);
5150 void R_SetupShader_DepthOrShadow(void)
5152 switch (vid.renderpath)
5154 case RENDERPATH_D3D9:
5156 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
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_DEPTH_OR_SHADOW, 0);
5168 case RENDERPATH_CGGL:
5170 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5173 case RENDERPATH_GL13:
5174 R_Mesh_TexBind(0, 0);
5175 R_Mesh_TexBind(1, 0);
5177 case RENDERPATH_GL11:
5178 R_Mesh_TexBind(0, 0);
5180 case RENDERPATH_SOFT:
5181 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
5186 void R_SetupShader_ShowDepth(void)
5188 switch (vid.renderpath)
5190 case RENDERPATH_D3D9:
5192 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5195 case RENDERPATH_D3D10:
5196 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5198 case RENDERPATH_D3D11:
5199 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5201 case RENDERPATH_GL20:
5202 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5204 case RENDERPATH_CGGL:
5206 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5209 case RENDERPATH_GL13:
5211 case RENDERPATH_GL11:
5213 case RENDERPATH_SOFT:
5214 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
5219 extern qboolean r_shadow_usingdeferredprepass;
5220 extern cvar_t r_shadow_deferred_8bitrange;
5221 extern rtexture_t *r_shadow_attenuationgradienttexture;
5222 extern rtexture_t *r_shadow_attenuation2dtexture;
5223 extern rtexture_t *r_shadow_attenuation3dtexture;
5224 extern qboolean r_shadow_usingshadowmap2d;
5225 extern qboolean r_shadow_usingshadowmaportho;
5226 extern float r_shadow_shadowmap_texturescale[2];
5227 extern float r_shadow_shadowmap_parameters[4];
5228 extern qboolean r_shadow_shadowmapvsdct;
5229 extern qboolean r_shadow_shadowmapsampler;
5230 extern int r_shadow_shadowmappcf;
5231 extern rtexture_t *r_shadow_shadowmap2dtexture;
5232 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5233 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5234 extern matrix4x4_t r_shadow_shadowmapmatrix;
5235 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5236 extern int r_shadow_prepass_width;
5237 extern int r_shadow_prepass_height;
5238 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5239 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5240 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
5241 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5242 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5243 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5245 // a blendfunc allows colormod if:
5246 // a) it can never keep the destination pixel invariant, or
5247 // b) it can keep the destination pixel invariant, and still can do so if colormodded
5248 // this is to prevent unintended side effects from colormod
5251 // IF there is a (s, sa) for which for all (d, da),
5252 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5253 // THEN, for this (s, sa) and all (colormod, d, da):
5254 // s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5255 // OBVIOUSLY, this means that
5256 // s*colormod * src(s*colormod, d, sa, da) = 0
5257 // dst(s*colormod, d, sa, da) = 1
5259 // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5261 // main condition to leave dst color invariant:
5262 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5264 // s * 0 + d * dst(s, d, sa, da) == d
5265 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5266 // => colormod is a problem for GL_SRC_COLOR only
5268 // s + d * dst(s, d, sa, da) == d
5270 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5271 // => colormod is never problematic for these
5272 // src == GL_SRC_COLOR:
5273 // s*s + d * dst(s, d, sa, da) == d
5275 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5276 // => colormod is never problematic for these
5277 // src == GL_ONE_MINUS_SRC_COLOR:
5278 // s*(1-s) + d * dst(s, d, sa, da) == d
5279 // => s == 0 or s == 1
5280 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5281 // => colormod is a problem for GL_SRC_COLOR only
5282 // src == GL_DST_COLOR
5283 // s*d + d * dst(s, d, sa, da) == d
5285 // => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5286 // => colormod is always a problem
5289 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5290 // => colormod is never problematic for these
5291 // => BUT, we do not know s! We must assume it is problematic
5292 // then... except in GL_ONE case, where we know all invariant
5294 // src == GL_ONE_MINUS_DST_COLOR
5295 // s*(1-d) + d * dst(s, d, sa, da) == d
5296 // => s == 0 (1-d is impossible to handle for our desired result)
5297 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5298 // => colormod is never problematic for these
5299 // src == GL_SRC_ALPHA
5300 // s*sa + d * dst(s, d, sa, da) == d
5301 // => s == 0, or sa == 0
5302 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5303 // => colormod breaks in the case GL_SRC_COLOR only
5304 // src == GL_ONE_MINUS_SRC_ALPHA
5305 // s*(1-sa) + d * dst(s, d, sa, da) == d
5306 // => s == 0, or sa == 1
5307 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5308 // => colormod breaks in the case GL_SRC_COLOR only
5309 // src == GL_DST_ALPHA
5310 // s*da + d * dst(s, d, sa, da) == d
5312 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5313 // => colormod is never problematic for these
5318 case GL_ONE_MINUS_SRC_COLOR:
5320 case GL_ONE_MINUS_SRC_ALPHA:
5321 if(dst == GL_SRC_COLOR)
5326 case GL_ONE_MINUS_DST_COLOR:
5328 case GL_ONE_MINUS_DST_ALPHA:
5338 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)
5340 // select a permutation of the lighting shader appropriate to this
5341 // combination of texture, entity, light source, and fogging, only use the
5342 // minimum features necessary to avoid wasting rendering time in the
5343 // fragment shader on features that are not being used
5344 unsigned int permutation = 0;
5345 unsigned int mode = 0;
5346 qboolean allow_colormod;
5347 static float dummy_colormod[3] = {1, 1, 1};
5348 float *colormod = rsurface.colormod;
5350 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5351 if (rsurfacepass == RSURFPASS_BACKGROUND)
5353 // distorted background
5354 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5356 mode = SHADERMODE_WATER;
5357 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
5358 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
5359 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
5361 // this is the right thing to do for wateralpha
5362 GL_BlendFunc(GL_ONE, GL_ZERO);
5363 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5367 // this is the right thing to do for entity alpha
5368 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5369 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5372 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5374 mode = SHADERMODE_REFRACTION;
5375 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5376 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5380 mode = SHADERMODE_GENERIC;
5381 permutation |= SHADERPERMUTATION_DIFFUSE;
5382 GL_BlendFunc(GL_ONE, GL_ZERO);
5383 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5385 GL_AlphaTest(false);
5387 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5389 if (r_glsl_offsetmapping.integer)
5391 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5392 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5393 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5394 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5395 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5397 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5398 if (r_glsl_offsetmapping_reliefmapping.integer)
5399 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5402 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5403 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5404 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5405 permutation |= SHADERPERMUTATION_ALPHAKILL;
5406 // normalmap (deferred prepass), may use alpha test on diffuse
5407 mode = SHADERMODE_DEFERREDGEOMETRY;
5408 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5409 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5410 GL_AlphaTest(false);
5411 GL_BlendFunc(GL_ONE, GL_ZERO);
5412 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5414 else if (rsurfacepass == RSURFPASS_RTLIGHT)
5416 if (r_glsl_offsetmapping.integer)
5418 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5419 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5420 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5421 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5422 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5424 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5425 if (r_glsl_offsetmapping_reliefmapping.integer)
5426 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5429 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5430 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5432 mode = SHADERMODE_LIGHTSOURCE;
5433 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5434 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5435 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5436 permutation |= SHADERPERMUTATION_CUBEFILTER;
5437 if (diffusescale > 0)
5438 permutation |= SHADERPERMUTATION_DIFFUSE;
5439 if (specularscale > 0)
5440 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5441 if (r_refdef.fogenabled)
5442 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5443 if (rsurface.texture->colormapping)
5444 permutation |= SHADERPERMUTATION_COLORMAPPING;
5445 if (r_shadow_usingshadowmap2d)
5447 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5448 if(r_shadow_shadowmapvsdct)
5449 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5451 if (r_shadow_shadowmapsampler)
5452 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5453 if (r_shadow_shadowmappcf > 1)
5454 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5455 else if (r_shadow_shadowmappcf)
5456 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5458 if (rsurface.texture->reflectmasktexture)
5459 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5460 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5461 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5462 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5464 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5466 if (r_glsl_offsetmapping.integer)
5468 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5469 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5470 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5471 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5472 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5474 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5475 if (r_glsl_offsetmapping_reliefmapping.integer)
5476 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5479 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5480 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5481 // unshaded geometry (fullbright or ambient model lighting)
5482 mode = SHADERMODE_FLATCOLOR;
5483 ambientscale = diffusescale = specularscale = 0;
5484 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5485 permutation |= SHADERPERMUTATION_GLOW;
5486 if (r_refdef.fogenabled)
5487 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5488 if (rsurface.texture->colormapping)
5489 permutation |= SHADERPERMUTATION_COLORMAPPING;
5490 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5492 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5493 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5495 if (r_shadow_shadowmapsampler)
5496 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5497 if (r_shadow_shadowmappcf > 1)
5498 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5499 else if (r_shadow_shadowmappcf)
5500 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5502 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5503 permutation |= SHADERPERMUTATION_REFLECTION;
5504 if (rsurface.texture->reflectmasktexture)
5505 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5506 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5507 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5508 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5510 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5512 if (r_glsl_offsetmapping.integer)
5514 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5515 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5516 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5517 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5518 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5520 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5521 if (r_glsl_offsetmapping_reliefmapping.integer)
5522 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5525 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5526 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5527 // directional model lighting
5528 mode = SHADERMODE_LIGHTDIRECTION;
5529 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5530 permutation |= SHADERPERMUTATION_GLOW;
5531 permutation |= SHADERPERMUTATION_DIFFUSE;
5532 if (specularscale > 0)
5533 permutation |= SHADERPERMUTATION_SPECULAR;
5534 if (r_refdef.fogenabled)
5535 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5536 if (rsurface.texture->colormapping)
5537 permutation |= SHADERPERMUTATION_COLORMAPPING;
5538 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5540 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5541 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5543 if (r_shadow_shadowmapsampler)
5544 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5545 if (r_shadow_shadowmappcf > 1)
5546 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5547 else if (r_shadow_shadowmappcf)
5548 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5550 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5551 permutation |= SHADERPERMUTATION_REFLECTION;
5552 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5553 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5554 if (rsurface.texture->reflectmasktexture)
5555 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5556 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5557 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5558 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5560 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5562 if (r_glsl_offsetmapping.integer)
5564 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5565 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5566 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5567 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5568 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5570 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5571 if (r_glsl_offsetmapping_reliefmapping.integer)
5572 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5575 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5576 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5577 // ambient model lighting
5578 mode = SHADERMODE_LIGHTDIRECTION;
5579 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5580 permutation |= SHADERPERMUTATION_GLOW;
5581 if (r_refdef.fogenabled)
5582 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5583 if (rsurface.texture->colormapping)
5584 permutation |= SHADERPERMUTATION_COLORMAPPING;
5585 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5587 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5588 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5590 if (r_shadow_shadowmapsampler)
5591 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5592 if (r_shadow_shadowmappcf > 1)
5593 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5594 else if (r_shadow_shadowmappcf)
5595 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5597 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5598 permutation |= SHADERPERMUTATION_REFLECTION;
5599 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5600 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5601 if (rsurface.texture->reflectmasktexture)
5602 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5603 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5604 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5605 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5609 if (r_glsl_offsetmapping.integer)
5611 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5612 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5613 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5614 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5615 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5617 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5618 if (r_glsl_offsetmapping_reliefmapping.integer)
5619 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5622 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5623 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5625 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5626 permutation |= SHADERPERMUTATION_GLOW;
5627 if (r_refdef.fogenabled)
5628 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5629 if (rsurface.texture->colormapping)
5630 permutation |= SHADERPERMUTATION_COLORMAPPING;
5631 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5633 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5634 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5636 if (r_shadow_shadowmapsampler)
5637 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5638 if (r_shadow_shadowmappcf > 1)
5639 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5640 else if (r_shadow_shadowmappcf)
5641 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5643 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5644 permutation |= SHADERPERMUTATION_REFLECTION;
5645 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5646 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5647 if (rsurface.texture->reflectmasktexture)
5648 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5649 if (FAKELIGHT_ENABLED)
5651 // fake lightmapping (q1bsp, q3bsp, fullbright map)
5652 mode = SHADERMODE_FAKELIGHT;
5653 permutation |= SHADERPERMUTATION_DIFFUSE;
5654 if (specularscale > 0)
5655 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5657 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5659 // deluxemapping (light direction texture)
5660 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5661 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5663 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5664 permutation |= SHADERPERMUTATION_DIFFUSE;
5665 if (specularscale > 0)
5666 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5668 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5670 // fake deluxemapping (uniform light direction in tangentspace)
5671 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5672 permutation |= SHADERPERMUTATION_DIFFUSE;
5673 if (specularscale > 0)
5674 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5676 else if (rsurface.uselightmaptexture)
5678 // ordinary lightmapping (q1bsp, q3bsp)
5679 mode = SHADERMODE_LIGHTMAP;
5683 // ordinary vertex coloring (q3bsp)
5684 mode = SHADERMODE_VERTEXCOLOR;
5686 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5687 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5688 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5691 colormod = dummy_colormod;
5692 switch(vid.renderpath)
5694 case RENDERPATH_D3D9:
5696 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);
5697 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5698 R_SetupShader_SetPermutationHLSL(mode, permutation);
5699 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5700 if (mode == SHADERMODE_LIGHTSOURCE)
5702 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5703 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5707 if (mode == SHADERMODE_LIGHTDIRECTION)
5709 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5712 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5713 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5714 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5715 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5716 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5718 if (mode == SHADERMODE_LIGHTSOURCE)
5720 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5721 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5722 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5723 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5724 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5726 // additive passes are only darkened by fog, not tinted
5727 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5728 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5732 if (mode == SHADERMODE_FLATCOLOR)
5734 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5736 else if (mode == SHADERMODE_LIGHTDIRECTION)
5738 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]);
5739 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5740 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);
5741 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);
5742 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5743 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5744 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5748 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5749 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5750 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);
5751 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);
5752 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5754 // additive passes are only darkened by fog, not tinted
5755 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5756 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5758 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5759 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);
5760 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5761 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5762 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5763 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5764 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5765 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5766 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5767 if (mode == SHADERMODE_WATER)
5768 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5770 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5771 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5772 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5773 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));
5774 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5775 if (rsurface.texture->pantstexture)
5776 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5778 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5779 if (rsurface.texture->shirttexture)
5780 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5782 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5783 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5784 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5785 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5786 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5787 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5788 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5789 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5791 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5792 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5793 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5794 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5795 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5796 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5797 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5798 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5799 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5800 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5801 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5802 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5803 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5804 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5805 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5806 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5807 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5808 if (rsurfacepass == RSURFPASS_BACKGROUND)
5810 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5811 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5812 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5816 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5818 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5819 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5820 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5821 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5822 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5824 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5825 if (rsurface.rtlight)
5827 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5828 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5833 case RENDERPATH_D3D10:
5834 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5836 case RENDERPATH_D3D11:
5837 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5839 case RENDERPATH_GL20:
5840 if (!vid.useinterleavedarrays)
5842 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);
5843 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5844 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5845 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5846 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5847 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5848 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5849 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5853 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);
5854 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5856 R_SetupShader_SetPermutationGLSL(mode, permutation);
5857 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5858 if (mode == SHADERMODE_LIGHTSOURCE)
5860 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5861 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5862 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5863 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5864 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5865 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);
5867 // additive passes are only darkened by fog, not tinted
5868 if (r_glsl_permutation->loc_FogColor >= 0)
5869 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5870 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5874 if (mode == SHADERMODE_FLATCOLOR)
5876 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5878 else if (mode == SHADERMODE_LIGHTDIRECTION)
5880 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]);
5881 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]);
5882 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);
5883 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);
5884 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);
5885 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]);
5886 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]);
5890 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]);
5891 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]);
5892 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);
5893 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);
5894 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);
5896 // additive passes are only darkened by fog, not tinted
5897 if (r_glsl_permutation->loc_FogColor >= 0)
5899 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5900 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5902 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5904 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);
5905 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]);
5906 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]);
5907 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]);
5908 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]);
5909 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5910 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5911 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5912 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]);
5914 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5915 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5916 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5917 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]);
5918 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]);
5920 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5921 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));
5922 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5923 if (r_glsl_permutation->loc_Color_Pants >= 0)
5925 if (rsurface.texture->pantstexture)
5926 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5928 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5930 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5932 if (rsurface.texture->shirttexture)
5933 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5935 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5937 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]);
5938 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5939 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5940 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5941 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5942 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]);
5943 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5945 // if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_texture_white );
5946 // if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_texture_white );
5947 // if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS , r_texture_gammaramps );
5948 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5949 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5950 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5951 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5952 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5953 if (r_glsl_permutation->loc_Texture_SecondaryColor >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5954 if (r_glsl_permutation->loc_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5955 if (r_glsl_permutation->loc_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5956 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5957 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5958 if (r_glsl_permutation->loc_Texture_ReflectMask >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5959 if (r_glsl_permutation->loc_Texture_ReflectCube >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5960 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5961 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5962 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5963 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5964 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5965 if (rsurfacepass == RSURFPASS_BACKGROUND)
5967 if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5968 else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5969 if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5973 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5975 // if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5976 // if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5977 if (r_glsl_permutation->loc_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5978 if (r_glsl_permutation->loc_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5979 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5981 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture );
5982 if (rsurface.rtlight)
5984 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5985 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5990 case RENDERPATH_CGGL:
5992 if (!vid.useinterleavedarrays)
5994 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);
5995 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5996 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5997 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5998 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5999 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
6000 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
6001 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
6005 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);
6006 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
6008 R_SetupShader_SetPermutationCG(mode, permutation);
6009 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
6010 if (mode == SHADERMODE_LIGHTSOURCE)
6012 if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
6013 if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6017 if (mode == SHADERMODE_LIGHTDIRECTION)
6019 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
6022 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
6023 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
6024 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
6025 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6026 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
6029 if (mode == SHADERMODE_LIGHTSOURCE)
6031 if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6032 if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
6033 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
6034 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
6035 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
6037 // additive passes are only darkened by fog, not tinted
6038 if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
6039 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6043 if (mode == SHADERMODE_FLATCOLOR)
6045 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
6047 else if (mode == SHADERMODE_LIGHTDIRECTION)
6049 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
6050 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
6051 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
6052 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
6053 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
6054 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
6055 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
6059 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
6060 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
6061 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
6062 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
6063 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
6065 // additive passes are only darkened by fog, not tinted
6066 if (r_cg_permutation->fp_FogColor)
6068 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6069 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
6071 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6074 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
6075 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
6076 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
6077 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
6078 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
6079 if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
6080 if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
6081 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6082 if (r_cg_permutation->fp_NormalmapScrollBlend) cgGLSetParameter2f(r_cg_permutation->fp_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
6084 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
6085 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
6086 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
6087 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
6088 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6089 if (r_cg_permutation->fp_Color_Pants)
6091 if (rsurface.texture->pantstexture)
6092 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6094 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
6097 if (r_cg_permutation->fp_Color_Shirt)
6099 if (rsurface.texture->shirttexture)
6100 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6102 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
6105 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
6106 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
6107 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
6108 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
6109 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
6110 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
6111 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6113 // if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_texture_white );CHECKCGERROR
6114 // if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_texture_white );CHECKCGERROR
6115 // if (r_cg_permutation->fp_Texture_GammaRamps ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps , r_texture_gammaramps );CHECKCGERROR
6116 if (r_cg_permutation->fp_Texture_Normal ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal , rsurface.texture->nmaptexture );CHECKCGERROR
6117 if (r_cg_permutation->fp_Texture_Color ) CG_BindTexture(r_cg_permutation->fp_Texture_Color , rsurface.texture->basetexture );CHECKCGERROR
6118 if (r_cg_permutation->fp_Texture_Gloss ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss , rsurface.texture->glosstexture );CHECKCGERROR
6119 if (r_cg_permutation->fp_Texture_Glow ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow , rsurface.texture->glowtexture );CHECKCGERROR
6120 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture );CHECKCGERROR
6121 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );CHECKCGERROR
6122 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );CHECKCGERROR
6123 if (r_cg_permutation->fp_Texture_SecondaryGlow ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );CHECKCGERROR
6124 if (r_cg_permutation->fp_Texture_Pants ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants , rsurface.texture->pantstexture );CHECKCGERROR
6125 if (r_cg_permutation->fp_Texture_Shirt ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt , rsurface.texture->shirttexture );CHECKCGERROR
6126 if (r_cg_permutation->fp_Texture_ReflectMask ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask , rsurface.texture->reflectmasktexture );CHECKCGERROR
6127 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
6128 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture );CHECKCGERROR
6129 if (r_cg_permutation->fp_Texture_FogMask ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask , r_texture_fogattenuation );CHECKCGERROR
6130 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
6131 if (r_cg_permutation->fp_Texture_Deluxemap ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
6132 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
6133 if (rsurfacepass == RSURFPASS_BACKGROUND)
6135 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
6136 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
6137 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
6141 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
6143 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
6144 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
6145 if (r_cg_permutation->fp_Texture_ScreenDiffuse ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );CHECKCGERROR
6146 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );CHECKCGERROR
6147 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6149 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
6150 if (rsurface.rtlight)
6152 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
6153 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
6160 case RENDERPATH_GL13:
6161 case RENDERPATH_GL11:
6163 case RENDERPATH_SOFT:
6164 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);
6165 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
6166 R_SetupShader_SetPermutationSoft(mode, permutation);
6167 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
6168 if (mode == SHADERMODE_LIGHTSOURCE)
6170 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
6171 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
6172 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
6173 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
6174 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
6175 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
6177 // additive passes are only darkened by fog, not tinted
6178 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
6179 DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6183 if (mode == SHADERMODE_FLATCOLOR)
6185 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
6187 else if (mode == SHADERMODE_LIGHTDIRECTION)
6189 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_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]);
6190 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
6191 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_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);
6192 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
6193 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
6194 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_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]);
6195 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
6199 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
6200 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
6201 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_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);
6202 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_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);
6203 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
6205 // additive passes are only darkened by fog, not tinted
6206 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6207 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
6209 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6210 DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_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);
6211 DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
6212 DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
6213 DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
6214 DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
6215 DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
6216 DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
6217 DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6218 DPSOFTRAST_Uniform2fARB(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
6220 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
6221 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
6222 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
6223 DPSOFTRAST_Uniform2fARB(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6224 DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6226 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
6227 DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
6228 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
6229 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
6231 if (rsurface.texture->pantstexture)
6232 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6234 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
6236 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
6238 if (rsurface.texture->shirttexture)
6239 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6241 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
6243 DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
6244 DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
6245 DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
6246 DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
6247 DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
6248 DPSOFTRAST_Uniform2fARB(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6249 DPSOFTRAST_Uniform2fARB(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6251 // R_Mesh_TexBind(GL20TU_FIRST , r_texture_white );
6252 // R_Mesh_TexBind(GL20TU_SECOND , r_texture_white );
6253 // R_Mesh_TexBind(GL20TU_GAMMARAMPS , r_texture_gammaramps );
6254 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
6255 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
6256 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
6257 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
6258 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
6259 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
6260 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
6261 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
6262 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
6263 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
6264 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
6265 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
6266 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
6267 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
6268 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
6269 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
6270 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
6271 if (rsurfacepass == RSURFPASS_BACKGROUND)
6273 if(DPSOFTRAST_UNIFORM_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
6274 else if(DPSOFTRAST_UNIFORM_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
6275 if(DPSOFTRAST_UNIFORM_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
6279 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
6281 // R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
6282 // R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
6283 R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
6284 R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
6285 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6287 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture );
6288 if (rsurface.rtlight)
6290 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
6291 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
6298 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6300 // select a permutation of the lighting shader appropriate to this
6301 // combination of texture, entity, light source, and fogging, only use the
6302 // minimum features necessary to avoid wasting rendering time in the
6303 // fragment shader on features that are not being used
6304 unsigned int permutation = 0;
6305 unsigned int mode = 0;
6306 const float *lightcolorbase = rtlight->currentcolor;
6307 float ambientscale = rtlight->ambientscale;
6308 float diffusescale = rtlight->diffusescale;
6309 float specularscale = rtlight->specularscale;
6310 // this is the location of the light in view space
6311 vec3_t viewlightorigin;
6312 // this transforms from view space (camera) to light space (cubemap)
6313 matrix4x4_t viewtolight;
6314 matrix4x4_t lighttoview;
6315 float viewtolight16f[16];
6316 float range = 1.0f / r_shadow_deferred_8bitrange.value;
6318 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6319 if (rtlight->currentcubemap != r_texture_whitecube)
6320 permutation |= SHADERPERMUTATION_CUBEFILTER;
6321 if (diffusescale > 0)
6322 permutation |= SHADERPERMUTATION_DIFFUSE;
6323 if (specularscale > 0)
6324 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6325 if (r_shadow_usingshadowmap2d)
6327 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6328 if (r_shadow_shadowmapvsdct)
6329 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6331 if (r_shadow_shadowmapsampler)
6332 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6333 if (r_shadow_shadowmappcf > 1)
6334 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6335 else if (r_shadow_shadowmappcf)
6336 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6338 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6339 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6340 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6341 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6342 switch(vid.renderpath)
6344 case RENDERPATH_D3D9:
6346 R_SetupShader_SetPermutationHLSL(mode, permutation);
6347 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6348 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6349 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
6350 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
6351 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6352 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6353 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6354 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6355 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6356 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6358 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
6359 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
6360 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
6361 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
6362 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
6363 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
6366 case RENDERPATH_D3D10:
6367 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6369 case RENDERPATH_D3D11:
6370 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6372 case RENDERPATH_GL20:
6373 R_SetupShader_SetPermutationGLSL(mode, permutation);
6374 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6375 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
6376 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);
6377 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);
6378 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);
6379 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]);
6380 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]);
6381 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));
6382 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]);
6383 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6385 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
6386 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
6387 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
6388 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
6389 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
6390 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
6392 case RENDERPATH_CGGL:
6394 R_SetupShader_SetPermutationCG(mode, permutation);
6395 if (r_cg_permutation->fp_LightPosition ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6396 if (r_cg_permutation->fp_ViewToLight ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6397 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
6398 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
6399 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
6400 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
6401 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
6402 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
6403 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
6404 if (r_cg_permutation->fp_PixelToScreenTexCoord ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6406 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
6407 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
6408 if (r_cg_permutation->fp_Texture_ScreenNormalMap ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
6409 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
6410 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
6411 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
6414 case RENDERPATH_GL13:
6415 case RENDERPATH_GL11:
6417 case RENDERPATH_SOFT:
6418 R_SetupShader_SetPermutationGLSL(mode, permutation);
6419 DPSOFTRAST_Uniform3fARB( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6420 DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
6421 DPSOFTRAST_Uniform3fARB( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
6422 DPSOFTRAST_Uniform3fARB( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
6423 DPSOFTRAST_Uniform3fARB( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6424 DPSOFTRAST_Uniform2fARB( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6425 DPSOFTRAST_Uniform4fARB( DPSOFTRAST_UNIFORM_ShadowMap_Parameters , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6426 DPSOFTRAST_Uniform1fARB( DPSOFTRAST_UNIFORM_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6427 DPSOFTRAST_Uniform2fARB( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6428 DPSOFTRAST_Uniform2fARB(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6430 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
6431 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
6432 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
6433 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
6434 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
6435 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
6440 #define SKINFRAME_HASH 1024
6444 int loadsequence; // incremented each level change
6445 memexpandablearray_t array;
6446 skinframe_t *hash[SKINFRAME_HASH];
6449 r_skinframe_t r_skinframe;
6451 void R_SkinFrame_PrepareForPurge(void)
6453 r_skinframe.loadsequence++;
6454 // wrap it without hitting zero
6455 if (r_skinframe.loadsequence >= 200)
6456 r_skinframe.loadsequence = 1;
6459 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6463 // mark the skinframe as used for the purging code
6464 skinframe->loadsequence = r_skinframe.loadsequence;
6467 void R_SkinFrame_Purge(void)
6471 for (i = 0;i < SKINFRAME_HASH;i++)
6473 for (s = r_skinframe.hash[i];s;s = s->next)
6475 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6477 if (s->merged == s->base)
6479 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6480 R_PurgeTexture(s->stain );s->stain = NULL;
6481 R_PurgeTexture(s->merged);s->merged = NULL;
6482 R_PurgeTexture(s->base );s->base = NULL;
6483 R_PurgeTexture(s->pants );s->pants = NULL;
6484 R_PurgeTexture(s->shirt );s->shirt = NULL;
6485 R_PurgeTexture(s->nmap );s->nmap = NULL;
6486 R_PurgeTexture(s->gloss );s->gloss = NULL;
6487 R_PurgeTexture(s->glow );s->glow = NULL;
6488 R_PurgeTexture(s->fog );s->fog = NULL;
6489 R_PurgeTexture(s->reflect);s->reflect = NULL;
6490 s->loadsequence = 0;
6496 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6498 char basename[MAX_QPATH];
6500 Image_StripImageExtension(name, basename, sizeof(basename));
6502 if( last == NULL ) {
6504 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6505 item = r_skinframe.hash[hashindex];
6510 // linearly search through the hash bucket
6511 for( ; item ; item = item->next ) {
6512 if( !strcmp( item->basename, basename ) ) {
6519 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6523 char basename[MAX_QPATH];
6525 Image_StripImageExtension(name, basename, sizeof(basename));
6527 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6528 for (item = r_skinframe.hash[hashindex];item;item = item->next)
6529 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6533 rtexture_t *dyntexture;
6534 // check whether its a dynamic texture
6535 dyntexture = CL_GetDynTexture( basename );
6536 if (!add && !dyntexture)
6538 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6539 memset(item, 0, sizeof(*item));
6540 strlcpy(item->basename, basename, sizeof(item->basename));
6541 item->base = dyntexture; // either NULL or dyntexture handle
6542 item->textureflags = textureflags;
6543 item->comparewidth = comparewidth;
6544 item->compareheight = compareheight;
6545 item->comparecrc = comparecrc;
6546 item->next = r_skinframe.hash[hashindex];
6547 r_skinframe.hash[hashindex] = item;
6549 else if( item->base == NULL )
6551 rtexture_t *dyntexture;
6552 // check whether its a dynamic texture
6553 // 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]
6554 dyntexture = CL_GetDynTexture( basename );
6555 item->base = dyntexture; // either NULL or dyntexture handle
6558 R_SkinFrame_MarkUsed(item);
6562 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6564 unsigned long long avgcolor[5], wsum; \
6572 for(pix = 0; pix < cnt; ++pix) \
6575 for(comp = 0; comp < 3; ++comp) \
6577 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6580 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6582 for(comp = 0; comp < 3; ++comp) \
6583 avgcolor[comp] += getpixel * w; \
6586 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6587 avgcolor[4] += getpixel; \
6589 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6591 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6592 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6593 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6594 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6597 extern cvar_t gl_picmip;
6598 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6601 unsigned char *pixels;
6602 unsigned char *bumppixels;
6603 unsigned char *basepixels = NULL;
6604 int basepixels_width = 0;
6605 int basepixels_height = 0;
6606 skinframe_t *skinframe;
6607 rtexture_t *ddsbase = NULL;
6608 qboolean ddshasalpha = false;
6609 float ddsavgcolor[4];
6610 char basename[MAX_QPATH];
6611 int miplevel = R_PicmipForFlags(textureflags);
6612 int savemiplevel = miplevel;
6615 if (cls.state == ca_dedicated)
6618 // return an existing skinframe if already loaded
6619 // if loading of the first image fails, don't make a new skinframe as it
6620 // would cause all future lookups of this to be missing
6621 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6622 if (skinframe && skinframe->base)
6625 Image_StripImageExtension(name, basename, sizeof(basename));
6627 // check for DDS texture file first
6628 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6630 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6631 if (basepixels == NULL)
6635 // FIXME handle miplevel
6637 if (developer_loading.integer)
6638 Con_Printf("loading skin \"%s\"\n", name);
6640 // we've got some pixels to store, so really allocate this new texture now
6642 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6643 skinframe->stain = NULL;
6644 skinframe->merged = NULL;
6645 skinframe->base = NULL;
6646 skinframe->pants = NULL;
6647 skinframe->shirt = NULL;
6648 skinframe->nmap = NULL;
6649 skinframe->gloss = NULL;
6650 skinframe->glow = NULL;
6651 skinframe->fog = NULL;
6652 skinframe->reflect = NULL;
6653 skinframe->hasalpha = false;
6657 skinframe->base = ddsbase;
6658 skinframe->hasalpha = ddshasalpha;
6659 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6660 if (r_loadfog && skinframe->hasalpha)
6661 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6662 //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]);
6666 basepixels_width = image_width;
6667 basepixels_height = image_height;
6668 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);
6669 if (textureflags & TEXF_ALPHA)
6671 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6673 if (basepixels[j] < 255)
6675 skinframe->hasalpha = true;
6679 if (r_loadfog && skinframe->hasalpha)
6681 // has transparent pixels
6682 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6683 for (j = 0;j < image_width * image_height * 4;j += 4)
6688 pixels[j+3] = basepixels[j+3];
6690 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);
6694 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6695 //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]);
6696 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6697 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6698 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6699 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6704 mymiplevel = savemiplevel;
6705 if (r_loadnormalmap)
6706 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);
6707 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6709 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6710 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6711 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6712 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6715 // _norm is the name used by tenebrae and has been adopted as standard
6716 if (r_loadnormalmap && skinframe->nmap == NULL)
6718 mymiplevel = savemiplevel;
6719 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6721 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);
6725 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6727 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6728 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6729 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);
6731 Mem_Free(bumppixels);
6733 else if (r_shadow_bumpscale_basetexture.value > 0)
6735 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6736 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6737 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);
6740 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6741 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6744 // _luma is supported only for tenebrae compatibility
6745 // _glow is the preferred name
6746 mymiplevel = savemiplevel;
6747 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))))
6749 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);
6750 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6751 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6752 Mem_Free(pixels);pixels = NULL;
6755 mymiplevel = savemiplevel;
6756 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6758 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);
6759 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6760 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6765 mymiplevel = savemiplevel;
6766 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6768 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);
6769 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6770 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6775 mymiplevel = savemiplevel;
6776 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6778 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);
6779 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6780 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6785 mymiplevel = savemiplevel;
6786 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6788 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);
6789 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6790 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6796 Mem_Free(basepixels);
6801 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6802 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6805 unsigned char *temp1, *temp2;
6806 skinframe_t *skinframe;
6808 if (cls.state == ca_dedicated)
6811 // if already loaded just return it, otherwise make a new skinframe
6812 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6813 if (skinframe && skinframe->base)
6816 skinframe->stain = NULL;
6817 skinframe->merged = NULL;
6818 skinframe->base = NULL;
6819 skinframe->pants = NULL;
6820 skinframe->shirt = NULL;
6821 skinframe->nmap = NULL;
6822 skinframe->gloss = NULL;
6823 skinframe->glow = NULL;
6824 skinframe->fog = NULL;
6825 skinframe->reflect = NULL;
6826 skinframe->hasalpha = false;
6828 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6832 if (developer_loading.integer)
6833 Con_Printf("loading 32bit skin \"%s\"\n", name);
6835 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6837 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6838 temp2 = temp1 + width * height * 4;
6839 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6840 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);
6843 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6844 if (textureflags & TEXF_ALPHA)
6846 for (i = 3;i < width * height * 4;i += 4)
6848 if (skindata[i] < 255)
6850 skinframe->hasalpha = true;
6854 if (r_loadfog && skinframe->hasalpha)
6856 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6857 memcpy(fogpixels, skindata, width * height * 4);
6858 for (i = 0;i < width * height * 4;i += 4)
6859 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6860 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6861 Mem_Free(fogpixels);
6865 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6866 //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]);
6871 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6875 skinframe_t *skinframe;
6877 if (cls.state == ca_dedicated)
6880 // if already loaded just return it, otherwise make a new skinframe
6881 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6882 if (skinframe && skinframe->base)
6885 skinframe->stain = NULL;
6886 skinframe->merged = NULL;
6887 skinframe->base = NULL;
6888 skinframe->pants = NULL;
6889 skinframe->shirt = NULL;
6890 skinframe->nmap = NULL;
6891 skinframe->gloss = NULL;
6892 skinframe->glow = NULL;
6893 skinframe->fog = NULL;
6894 skinframe->reflect = NULL;
6895 skinframe->hasalpha = false;
6897 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6901 if (developer_loading.integer)
6902 Con_Printf("loading quake skin \"%s\"\n", name);
6904 // 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)
6905 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
6906 memcpy(skinframe->qpixels, skindata, width*height);
6907 skinframe->qwidth = width;
6908 skinframe->qheight = height;
6911 for (i = 0;i < width * height;i++)
6912 featuresmask |= palette_featureflags[skindata[i]];
6914 skinframe->hasalpha = false;
6915 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6916 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6917 skinframe->qgeneratemerged = true;
6918 skinframe->qgeneratebase = skinframe->qhascolormapping;
6919 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6921 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6922 //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]);
6927 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6931 unsigned char *skindata;
6933 if (!skinframe->qpixels)
6936 if (!skinframe->qhascolormapping)
6937 colormapped = false;
6941 if (!skinframe->qgeneratebase)
6946 if (!skinframe->qgeneratemerged)
6950 width = skinframe->qwidth;
6951 height = skinframe->qheight;
6952 skindata = skinframe->qpixels;
6954 if (skinframe->qgeneratenmap)
6956 unsigned char *temp1, *temp2;
6957 skinframe->qgeneratenmap = false;
6958 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6959 temp2 = temp1 + width * height * 4;
6960 // use either a custom palette or the quake palette
6961 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6962 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6963 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);
6967 if (skinframe->qgenerateglow)
6969 skinframe->qgenerateglow = false;
6970 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6975 skinframe->qgeneratebase = false;
6976 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);
6977 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6978 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6982 skinframe->qgeneratemerged = false;
6983 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);
6986 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6988 Mem_Free(skinframe->qpixels);
6989 skinframe->qpixels = NULL;
6993 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)
6996 skinframe_t *skinframe;
6998 if (cls.state == ca_dedicated)
7001 // if already loaded just return it, otherwise make a new skinframe
7002 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
7003 if (skinframe && skinframe->base)
7006 skinframe->stain = NULL;
7007 skinframe->merged = NULL;
7008 skinframe->base = NULL;
7009 skinframe->pants = NULL;
7010 skinframe->shirt = NULL;
7011 skinframe->nmap = NULL;
7012 skinframe->gloss = NULL;
7013 skinframe->glow = NULL;
7014 skinframe->fog = NULL;
7015 skinframe->reflect = NULL;
7016 skinframe->hasalpha = false;
7018 // if no data was provided, then clearly the caller wanted to get a blank skinframe
7022 if (developer_loading.integer)
7023 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
7025 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
7026 if (textureflags & TEXF_ALPHA)
7028 for (i = 0;i < width * height;i++)
7030 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
7032 skinframe->hasalpha = true;
7036 if (r_loadfog && skinframe->hasalpha)
7037 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
7040 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
7041 //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]);
7046 skinframe_t *R_SkinFrame_LoadMissing(void)
7048 skinframe_t *skinframe;
7050 if (cls.state == ca_dedicated)
7053 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
7054 skinframe->stain = NULL;
7055 skinframe->merged = NULL;
7056 skinframe->base = NULL;
7057 skinframe->pants = NULL;
7058 skinframe->shirt = NULL;
7059 skinframe->nmap = NULL;
7060 skinframe->gloss = NULL;
7061 skinframe->glow = NULL;
7062 skinframe->fog = NULL;
7063 skinframe->reflect = NULL;
7064 skinframe->hasalpha = false;
7066 skinframe->avgcolor[0] = rand() / RAND_MAX;
7067 skinframe->avgcolor[1] = rand() / RAND_MAX;
7068 skinframe->avgcolor[2] = rand() / RAND_MAX;
7069 skinframe->avgcolor[3] = 1;
7074 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
7075 typedef struct suffixinfo_s
7078 qboolean flipx, flipy, flipdiagonal;
7081 static suffixinfo_t suffix[3][6] =
7084 {"px", false, false, false},
7085 {"nx", false, false, false},
7086 {"py", false, false, false},
7087 {"ny", false, false, false},
7088 {"pz", false, false, false},
7089 {"nz", false, false, false}
7092 {"posx", false, false, false},
7093 {"negx", false, false, false},
7094 {"posy", false, false, false},
7095 {"negy", false, false, false},
7096 {"posz", false, false, false},
7097 {"negz", false, false, false}
7100 {"rt", true, false, true},
7101 {"lf", false, true, true},
7102 {"ft", true, true, false},
7103 {"bk", false, false, false},
7104 {"up", true, false, true},
7105 {"dn", true, false, true}
7109 static int componentorder[4] = {0, 1, 2, 3};
7111 rtexture_t *R_LoadCubemap(const char *basename)
7113 int i, j, cubemapsize;
7114 unsigned char *cubemappixels, *image_buffer;
7115 rtexture_t *cubemaptexture;
7117 // must start 0 so the first loadimagepixels has no requested width/height
7119 cubemappixels = NULL;
7120 cubemaptexture = NULL;
7121 // keep trying different suffix groups (posx, px, rt) until one loads
7122 for (j = 0;j < 3 && !cubemappixels;j++)
7124 // load the 6 images in the suffix group
7125 for (i = 0;i < 6;i++)
7127 // generate an image name based on the base and and suffix
7128 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
7130 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
7132 // an image loaded, make sure width and height are equal
7133 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
7135 // if this is the first image to load successfully, allocate the cubemap memory
7136 if (!cubemappixels && image_width >= 1)
7138 cubemapsize = image_width;
7139 // note this clears to black, so unavailable sides are black
7140 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
7142 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
7144 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);
7147 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
7149 Mem_Free(image_buffer);
7153 // if a cubemap loaded, upload it
7156 if (developer_loading.integer)
7157 Con_Printf("loading cubemap \"%s\"\n", basename);
7159 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
7160 Mem_Free(cubemappixels);
7164 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
7165 if (developer_loading.integer)
7167 Con_Printf("(tried tried images ");
7168 for (j = 0;j < 3;j++)
7169 for (i = 0;i < 6;i++)
7170 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
7171 Con_Print(" and was unable to find any of them).\n");
7174 return cubemaptexture;
7177 rtexture_t *R_GetCubemap(const char *basename)
7180 for (i = 0;i < r_texture_numcubemaps;i++)
7181 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
7182 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
7183 if (i >= MAX_CUBEMAPS)
7184 return r_texture_whitecube;
7185 r_texture_numcubemaps++;
7186 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
7187 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
7188 return r_texture_cubemaps[i].texture;
7191 void R_FreeCubemaps(void)
7194 for (i = 0;i < r_texture_numcubemaps;i++)
7196 if (developer_loading.integer)
7197 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
7198 if (r_texture_cubemaps[i].texture)
7199 R_FreeTexture(r_texture_cubemaps[i].texture);
7201 r_texture_numcubemaps = 0;
7204 void R_Main_FreeViewCache(void)
7206 if (r_refdef.viewcache.entityvisible)
7207 Mem_Free(r_refdef.viewcache.entityvisible);
7208 if (r_refdef.viewcache.world_pvsbits)
7209 Mem_Free(r_refdef.viewcache.world_pvsbits);
7210 if (r_refdef.viewcache.world_leafvisible)
7211 Mem_Free(r_refdef.viewcache.world_leafvisible);
7212 if (r_refdef.viewcache.world_surfacevisible)
7213 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7214 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
7217 void R_Main_ResizeViewCache(void)
7219 int numentities = r_refdef.scene.numentities;
7220 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
7221 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
7222 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
7223 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
7224 if (r_refdef.viewcache.maxentities < numentities)
7226 r_refdef.viewcache.maxentities = numentities;
7227 if (r_refdef.viewcache.entityvisible)
7228 Mem_Free(r_refdef.viewcache.entityvisible);
7229 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
7231 if (r_refdef.viewcache.world_numclusters != numclusters)
7233 r_refdef.viewcache.world_numclusters = numclusters;
7234 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
7235 if (r_refdef.viewcache.world_pvsbits)
7236 Mem_Free(r_refdef.viewcache.world_pvsbits);
7237 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
7239 if (r_refdef.viewcache.world_numleafs != numleafs)
7241 r_refdef.viewcache.world_numleafs = numleafs;
7242 if (r_refdef.viewcache.world_leafvisible)
7243 Mem_Free(r_refdef.viewcache.world_leafvisible);
7244 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
7246 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
7248 r_refdef.viewcache.world_numsurfaces = numsurfaces;
7249 if (r_refdef.viewcache.world_surfacevisible)
7250 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7251 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
7255 extern rtexture_t *loadingscreentexture;
7256 void gl_main_start(void)
7258 loadingscreentexture = NULL;
7259 r_texture_blanknormalmap = NULL;
7260 r_texture_white = NULL;
7261 r_texture_grey128 = NULL;
7262 r_texture_black = NULL;
7263 r_texture_whitecube = NULL;
7264 r_texture_normalizationcube = NULL;
7265 r_texture_fogattenuation = NULL;
7266 r_texture_fogheighttexture = NULL;
7267 r_texture_gammaramps = NULL;
7268 r_texture_numcubemaps = 0;
7270 r_loaddds = r_texture_dds_load.integer != 0;
7271 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
7273 switch(vid.renderpath)
7275 case RENDERPATH_GL20:
7276 case RENDERPATH_CGGL:
7277 case RENDERPATH_D3D9:
7278 case RENDERPATH_D3D10:
7279 case RENDERPATH_D3D11:
7280 case RENDERPATH_SOFT:
7281 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7282 Cvar_SetValueQuick(&gl_combine, 1);
7283 Cvar_SetValueQuick(&r_glsl, 1);
7284 r_loadnormalmap = true;
7288 case RENDERPATH_GL13:
7289 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7290 Cvar_SetValueQuick(&gl_combine, 1);
7291 Cvar_SetValueQuick(&r_glsl, 0);
7292 r_loadnormalmap = false;
7293 r_loadgloss = false;
7296 case RENDERPATH_GL11:
7297 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7298 Cvar_SetValueQuick(&gl_combine, 0);
7299 Cvar_SetValueQuick(&r_glsl, 0);
7300 r_loadnormalmap = false;
7301 r_loadgloss = false;
7307 R_FrameData_Reset();
7311 memset(r_queries, 0, sizeof(r_queries));
7313 r_qwskincache = NULL;
7314 r_qwskincache_size = 0;
7316 // set up r_skinframe loading system for textures
7317 memset(&r_skinframe, 0, sizeof(r_skinframe));
7318 r_skinframe.loadsequence = 1;
7319 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7321 r_main_texturepool = R_AllocTexturePool();
7322 R_BuildBlankTextures();
7324 if (vid.support.arb_texture_cube_map)
7327 R_BuildNormalizationCube();
7329 r_texture_fogattenuation = NULL;
7330 r_texture_fogheighttexture = NULL;
7331 r_texture_gammaramps = NULL;
7332 //r_texture_fogintensity = NULL;
7333 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7334 memset(&r_waterstate, 0, sizeof(r_waterstate));
7335 r_glsl_permutation = NULL;
7336 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7337 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7338 glslshaderstring = NULL;
7340 r_cg_permutation = NULL;
7341 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7342 Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7343 cgshaderstring = NULL;
7346 r_hlsl_permutation = NULL;
7347 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7348 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7349 hlslshaderstring = NULL;
7351 memset(&r_svbsp, 0, sizeof (r_svbsp));
7353 r_refdef.fogmasktable_density = 0;
7356 void gl_main_shutdown(void)
7359 R_FrameData_Reset();
7361 R_Main_FreeViewCache();
7363 switch(vid.renderpath)
7365 case RENDERPATH_GL11:
7366 case RENDERPATH_GL13:
7367 case RENDERPATH_GL20:
7368 case RENDERPATH_CGGL:
7370 qglDeleteQueriesARB(r_maxqueries, r_queries);
7372 case RENDERPATH_D3D9:
7373 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7375 case RENDERPATH_D3D10:
7376 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7378 case RENDERPATH_D3D11:
7379 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7381 case RENDERPATH_SOFT:
7387 memset(r_queries, 0, sizeof(r_queries));
7389 r_qwskincache = NULL;
7390 r_qwskincache_size = 0;
7392 // clear out the r_skinframe state
7393 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7394 memset(&r_skinframe, 0, sizeof(r_skinframe));
7397 Mem_Free(r_svbsp.nodes);
7398 memset(&r_svbsp, 0, sizeof (r_svbsp));
7399 R_FreeTexturePool(&r_main_texturepool);
7400 loadingscreentexture = NULL;
7401 r_texture_blanknormalmap = NULL;
7402 r_texture_white = NULL;
7403 r_texture_grey128 = NULL;
7404 r_texture_black = NULL;
7405 r_texture_whitecube = NULL;
7406 r_texture_normalizationcube = NULL;
7407 r_texture_fogattenuation = NULL;
7408 r_texture_fogheighttexture = NULL;
7409 r_texture_gammaramps = NULL;
7410 r_texture_numcubemaps = 0;
7411 //r_texture_fogintensity = NULL;
7412 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7413 memset(&r_waterstate, 0, sizeof(r_waterstate));
7416 r_glsl_permutation = NULL;
7417 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7418 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
7419 glslshaderstring = NULL;
7421 r_cg_permutation = NULL;
7422 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7423 Mem_ExpandableArray_FreeArray(&r_cg_permutationarray);
7424 cgshaderstring = NULL;
7427 r_hlsl_permutation = NULL;
7428 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7429 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
7430 hlslshaderstring = NULL;
7434 extern void CL_ParseEntityLump(char *entitystring);
7435 void gl_main_newmap(void)
7437 // FIXME: move this code to client
7438 char *entities, entname[MAX_QPATH];
7440 Mem_Free(r_qwskincache);
7441 r_qwskincache = NULL;
7442 r_qwskincache_size = 0;
7445 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7446 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7448 CL_ParseEntityLump(entities);
7452 if (cl.worldmodel->brush.entities)
7453 CL_ParseEntityLump(cl.worldmodel->brush.entities);
7455 R_Main_FreeViewCache();
7457 R_FrameData_Reset();
7460 void GL_Main_Init(void)
7462 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7464 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7465 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7466 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7467 if (gamemode == GAME_NEHAHRA)
7469 Cvar_RegisterVariable (&gl_fogenable);
7470 Cvar_RegisterVariable (&gl_fogdensity);
7471 Cvar_RegisterVariable (&gl_fogred);
7472 Cvar_RegisterVariable (&gl_foggreen);
7473 Cvar_RegisterVariable (&gl_fogblue);
7474 Cvar_RegisterVariable (&gl_fogstart);
7475 Cvar_RegisterVariable (&gl_fogend);
7476 Cvar_RegisterVariable (&gl_skyclip);
7478 Cvar_RegisterVariable(&r_motionblur);
7479 Cvar_RegisterVariable(&r_motionblur_maxblur);
7480 Cvar_RegisterVariable(&r_motionblur_bmin);
7481 Cvar_RegisterVariable(&r_motionblur_vmin);
7482 Cvar_RegisterVariable(&r_motionblur_vmax);
7483 Cvar_RegisterVariable(&r_motionblur_vcoeff);
7484 Cvar_RegisterVariable(&r_motionblur_randomize);
7485 Cvar_RegisterVariable(&r_damageblur);
7486 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7487 Cvar_RegisterVariable(&r_equalize_entities_minambient);
7488 Cvar_RegisterVariable(&r_equalize_entities_by);
7489 Cvar_RegisterVariable(&r_equalize_entities_to);
7490 Cvar_RegisterVariable(&r_depthfirst);
7491 Cvar_RegisterVariable(&r_useinfinitefarclip);
7492 Cvar_RegisterVariable(&r_farclip_base);
7493 Cvar_RegisterVariable(&r_farclip_world);
7494 Cvar_RegisterVariable(&r_nearclip);
7495 Cvar_RegisterVariable(&r_showbboxes);
7496 Cvar_RegisterVariable(&r_showsurfaces);
7497 Cvar_RegisterVariable(&r_showtris);
7498 Cvar_RegisterVariable(&r_shownormals);
7499 Cvar_RegisterVariable(&r_showlighting);
7500 Cvar_RegisterVariable(&r_showshadowvolumes);
7501 Cvar_RegisterVariable(&r_showcollisionbrushes);
7502 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7503 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7504 Cvar_RegisterVariable(&r_showdisabledepthtest);
7505 Cvar_RegisterVariable(&r_drawportals);
7506 Cvar_RegisterVariable(&r_drawentities);
7507 Cvar_RegisterVariable(&r_draw2d);
7508 Cvar_RegisterVariable(&r_drawworld);
7509 Cvar_RegisterVariable(&r_cullentities_trace);
7510 Cvar_RegisterVariable(&r_cullentities_trace_samples);
7511 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7512 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7513 Cvar_RegisterVariable(&r_cullentities_trace_delay);
7514 Cvar_RegisterVariable(&r_drawviewmodel);
7515 Cvar_RegisterVariable(&r_drawexteriormodel);
7516 Cvar_RegisterVariable(&r_speeds);
7517 Cvar_RegisterVariable(&r_fullbrights);
7518 Cvar_RegisterVariable(&r_wateralpha);
7519 Cvar_RegisterVariable(&r_dynamic);
7520 Cvar_RegisterVariable(&r_fakelight);
7521 Cvar_RegisterVariable(&r_fakelight_intensity);
7522 Cvar_RegisterVariable(&r_fullbright);
7523 Cvar_RegisterVariable(&r_shadows);
7524 Cvar_RegisterVariable(&r_shadows_darken);
7525 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7526 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7527 Cvar_RegisterVariable(&r_shadows_throwdistance);
7528 Cvar_RegisterVariable(&r_shadows_throwdirection);
7529 Cvar_RegisterVariable(&r_shadows_focus);
7530 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7531 Cvar_RegisterVariable(&r_q1bsp_skymasking);
7532 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7533 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7534 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7535 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7536 Cvar_RegisterVariable(&r_fog_exp2);
7537 Cvar_RegisterVariable(&r_drawfog);
7538 Cvar_RegisterVariable(&r_transparentdepthmasking);
7539 Cvar_RegisterVariable(&r_texture_dds_load);
7540 Cvar_RegisterVariable(&r_texture_dds_save);
7541 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7542 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7543 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7544 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7545 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7546 Cvar_RegisterVariable(&r_textureunits);
7547 Cvar_RegisterVariable(&gl_combine);
7548 Cvar_RegisterVariable(&r_glsl);
7549 Cvar_RegisterVariable(&r_glsl_deluxemapping);
7550 Cvar_RegisterVariable(&r_glsl_offsetmapping);
7551 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7552 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7553 Cvar_RegisterVariable(&r_glsl_postprocess);
7554 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7555 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7556 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7557 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7558 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
7559 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
7560 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
7561 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
7563 Cvar_RegisterVariable(&r_water);
7564 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7565 Cvar_RegisterVariable(&r_water_clippingplanebias);
7566 Cvar_RegisterVariable(&r_water_refractdistort);
7567 Cvar_RegisterVariable(&r_water_reflectdistort);
7568 Cvar_RegisterVariable(&r_water_scissormode);
7569 Cvar_RegisterVariable(&r_lerpsprites);
7570 Cvar_RegisterVariable(&r_lerpmodels);
7571 Cvar_RegisterVariable(&r_lerplightstyles);
7572 Cvar_RegisterVariable(&r_waterscroll);
7573 Cvar_RegisterVariable(&r_bloom);
7574 Cvar_RegisterVariable(&r_bloom_colorscale);
7575 Cvar_RegisterVariable(&r_bloom_brighten);
7576 Cvar_RegisterVariable(&r_bloom_blur);
7577 Cvar_RegisterVariable(&r_bloom_resolution);
7578 Cvar_RegisterVariable(&r_bloom_colorexponent);
7579 Cvar_RegisterVariable(&r_bloom_colorsubtract);
7580 Cvar_RegisterVariable(&r_hdr);
7581 Cvar_RegisterVariable(&r_hdr_scenebrightness);
7582 Cvar_RegisterVariable(&r_hdr_glowintensity);
7583 Cvar_RegisterVariable(&r_hdr_range);
7584 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7585 Cvar_RegisterVariable(&developer_texturelogging);
7586 Cvar_RegisterVariable(&gl_lightmaps);
7587 Cvar_RegisterVariable(&r_test);
7588 Cvar_RegisterVariable(&r_glsl_saturation);
7589 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
7590 Cvar_RegisterVariable(&r_framedatasize);
7591 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7592 Cvar_SetValue("r_fullbrights", 0);
7593 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7595 Cvar_RegisterVariable(&r_track_sprites);
7596 Cvar_RegisterVariable(&r_track_sprites_flags);
7597 Cvar_RegisterVariable(&r_track_sprites_scalew);
7598 Cvar_RegisterVariable(&r_track_sprites_scaleh);
7599 Cvar_RegisterVariable(&r_overheadsprites_perspective);
7600 Cvar_RegisterVariable(&r_overheadsprites_pushback);
7601 Cvar_RegisterVariable(&r_overheadsprites_scalex);
7602 Cvar_RegisterVariable(&r_overheadsprites_scaley);
7605 extern void R_Textures_Init(void);
7606 extern void GL_Draw_Init(void);
7607 extern void GL_Main_Init(void);
7608 extern void R_Shadow_Init(void);
7609 extern void R_Sky_Init(void);
7610 extern void GL_Surf_Init(void);
7611 extern void R_Particles_Init(void);
7612 extern void R_Explosion_Init(void);
7613 extern void gl_backend_init(void);
7614 extern void Sbar_Init(void);
7615 extern void R_LightningBeams_Init(void);
7616 extern void Mod_RenderInit(void);
7617 extern void Font_Init(void);
7619 void Render_Init(void)
7632 R_LightningBeams_Init();
7641 extern char *ENGINE_EXTENSIONS;
7644 gl_renderer = (const char *)qglGetString(GL_RENDERER);
7645 gl_vendor = (const char *)qglGetString(GL_VENDOR);
7646 gl_version = (const char *)qglGetString(GL_VERSION);
7647 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7651 if (!gl_platformextensions)
7652 gl_platformextensions = "";
7654 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7655 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7656 Con_Printf("GL_VERSION: %s\n", gl_version);
7657 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7658 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7660 VID_CheckExtensions();
7662 // LordHavoc: report supported extensions
7663 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7665 // clear to black (loading plaque will be seen over this)
7666 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7669 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7673 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7675 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7678 p = r_refdef.view.frustum + i;
7683 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7687 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7691 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7695 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7699 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7703 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7707 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7711 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7719 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7723 for (i = 0;i < numplanes;i++)
7730 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7734 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7738 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7742 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7746 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7750 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7754 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7758 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7766 //==================================================================================
7768 // LordHavoc: this stores temporary data used within the same frame
7770 typedef struct r_framedata_mem_s
7772 struct r_framedata_mem_s *purge; // older mem block to free on next frame
7773 size_t size; // how much usable space
7774 size_t current; // how much space in use
7775 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
7776 size_t wantedsize; // how much space was allocated
7777 unsigned char *data; // start of real data (16byte aligned)
7781 static r_framedata_mem_t *r_framedata_mem;
7783 void R_FrameData_Reset(void)
7785 while (r_framedata_mem)
7787 r_framedata_mem_t *next = r_framedata_mem->purge;
7788 Mem_Free(r_framedata_mem);
7789 r_framedata_mem = next;
7793 void R_FrameData_Resize(void)
7796 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7797 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
7798 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
7800 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
7801 newmem->wantedsize = wantedsize;
7802 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
7803 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
7804 newmem->current = 0;
7806 newmem->purge = r_framedata_mem;
7807 r_framedata_mem = newmem;
7811 void R_FrameData_NewFrame(void)
7813 R_FrameData_Resize();
7814 if (!r_framedata_mem)
7816 // if we ran out of space on the last frame, free the old memory now
7817 while (r_framedata_mem->purge)
7819 // repeatedly remove the second item in the list, leaving only head
7820 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
7821 Mem_Free(r_framedata_mem->purge);
7822 r_framedata_mem->purge = next;
7824 // reset the current mem pointer
7825 r_framedata_mem->current = 0;
7826 r_framedata_mem->mark = 0;
7829 void *R_FrameData_Alloc(size_t size)
7833 // align to 16 byte boundary - the data pointer is already aligned, so we
7834 // only need to ensure the size of every allocation is also aligned
7835 size = (size + 15) & ~15;
7837 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
7839 // emergency - we ran out of space, allocate more memory
7840 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
7841 R_FrameData_Resize();
7844 data = r_framedata_mem->data + r_framedata_mem->current;
7845 r_framedata_mem->current += size;
7847 // count the usage for stats
7848 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
7849 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
7851 return (void *)data;
7854 void *R_FrameData_Store(size_t size, void *data)
7856 void *d = R_FrameData_Alloc(size);
7858 memcpy(d, data, size);
7862 void R_FrameData_SetMark(void)
7864 if (!r_framedata_mem)
7866 r_framedata_mem->mark = r_framedata_mem->current;
7869 void R_FrameData_ReturnToMark(void)
7871 if (!r_framedata_mem)
7873 r_framedata_mem->current = r_framedata_mem->mark;
7876 //==================================================================================
7878 // LordHavoc: animcache originally written by Echon, rewritten since then
7881 * Animation cache prevents re-generating mesh data for an animated model
7882 * multiple times in one frame for lighting, shadowing, reflections, etc.
7885 void R_AnimCache_Free(void)
7889 void R_AnimCache_ClearCache(void)
7892 entity_render_t *ent;
7894 for (i = 0;i < r_refdef.scene.numentities;i++)
7896 ent = r_refdef.scene.entities[i];
7897 ent->animcache_vertex3f = NULL;
7898 ent->animcache_normal3f = NULL;
7899 ent->animcache_svector3f = NULL;
7900 ent->animcache_tvector3f = NULL;
7901 ent->animcache_vertexmesh = NULL;
7902 ent->animcache_vertex3fbuffer = NULL;
7903 ent->animcache_vertexmeshbuffer = NULL;
7907 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7911 // check if we need the meshbuffers
7912 if (!vid.useinterleavedarrays)
7915 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7916 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7917 // TODO: upload vertex3f buffer?
7918 if (ent->animcache_vertexmesh)
7920 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7921 for (i = 0;i < numvertices;i++)
7922 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7923 if (ent->animcache_svector3f)
7924 for (i = 0;i < numvertices;i++)
7925 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7926 if (ent->animcache_tvector3f)
7927 for (i = 0;i < numvertices;i++)
7928 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7929 if (ent->animcache_normal3f)
7930 for (i = 0;i < numvertices;i++)
7931 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7932 // TODO: upload vertexmeshbuffer?
7936 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7938 dp_model_t *model = ent->model;
7940 // see if it's already cached this frame
7941 if (ent->animcache_vertex3f)
7943 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7944 if (wantnormals || wanttangents)
7946 if (ent->animcache_normal3f)
7947 wantnormals = false;
7948 if (ent->animcache_svector3f)
7949 wanttangents = false;
7950 if (wantnormals || wanttangents)
7952 numvertices = model->surfmesh.num_vertices;
7954 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7957 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7958 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7960 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7961 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7967 // see if this ent is worth caching
7968 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7970 // get some memory for this entity and generate mesh data
7971 numvertices = model->surfmesh.num_vertices;
7972 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7974 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7977 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7978 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7980 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7981 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7986 void R_AnimCache_CacheVisibleEntities(void)
7989 qboolean wantnormals = true;
7990 qboolean wanttangents = !r_showsurfaces.integer;
7992 switch(vid.renderpath)
7994 case RENDERPATH_GL20:
7995 case RENDERPATH_CGGL:
7996 case RENDERPATH_D3D9:
7997 case RENDERPATH_D3D10:
7998 case RENDERPATH_D3D11:
8000 case RENDERPATH_GL13:
8001 case RENDERPATH_GL11:
8002 wanttangents = false;
8004 case RENDERPATH_SOFT:
8008 if (r_shownormals.integer)
8009 wanttangents = wantnormals = true;
8011 // TODO: thread this
8012 // NOTE: R_PrepareRTLights() also caches entities
8014 for (i = 0;i < r_refdef.scene.numentities;i++)
8015 if (r_refdef.viewcache.entityvisible[i])
8016 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
8019 //==================================================================================
8021 static void R_View_UpdateEntityLighting (void)
8024 entity_render_t *ent;
8025 vec3_t tempdiffusenormal, avg;
8026 vec_t f, fa, fd, fdd;
8027 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
8029 for (i = 0;i < r_refdef.scene.numentities;i++)
8031 ent = r_refdef.scene.entities[i];
8033 // skip unseen models
8034 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
8038 if (ent->model && ent->model->brush.num_leafs)
8040 // TODO: use modellight for r_ambient settings on world?
8041 VectorSet(ent->modellight_ambient, 0, 0, 0);
8042 VectorSet(ent->modellight_diffuse, 0, 0, 0);
8043 VectorSet(ent->modellight_lightdir, 0, 0, 1);
8047 // fetch the lighting from the worldmodel data
8048 VectorClear(ent->modellight_ambient);
8049 VectorClear(ent->modellight_diffuse);
8050 VectorClear(tempdiffusenormal);
8051 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
8054 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8056 // complete lightning for lit sprites
8057 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
8058 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
8060 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
8061 org[2] = org[2] + r_overheadsprites_pushback.value;
8062 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, ent->modellight_lightdir, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
8065 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
8067 if(ent->flags & RENDER_EQUALIZE)
8069 // first fix up ambient lighting...
8070 if(r_equalize_entities_minambient.value > 0)
8072 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
8075 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
8076 if(fa < r_equalize_entities_minambient.value * fd)
8079 // fa'/fd' = minambient
8080 // fa'+0.25*fd' = fa+0.25*fd
8082 // fa' = fd' * minambient
8083 // fd'*(0.25+minambient) = fa+0.25*fd
8085 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
8086 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
8088 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
8089 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
8090 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
8091 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
8096 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
8098 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
8099 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
8103 // adjust brightness and saturation to target
8104 avg[0] = avg[1] = avg[2] = fa / f;
8105 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
8106 avg[0] = avg[1] = avg[2] = fd / f;
8107 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
8113 VectorSet(ent->modellight_ambient, 1, 1, 1);
8115 // move the light direction into modelspace coordinates for lighting code
8116 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
8117 if(VectorLength2(ent->modellight_lightdir) == 0)
8118 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
8119 VectorNormalize(ent->modellight_lightdir);
8123 #define MAX_LINEOFSIGHTTRACES 64
8125 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
8128 vec3_t boxmins, boxmaxs;
8131 dp_model_t *model = r_refdef.scene.worldmodel;
8133 if (!model || !model->brush.TraceLineOfSight)
8136 // expand the box a little
8137 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
8138 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
8139 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
8140 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
8141 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
8142 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
8144 // return true if eye is inside enlarged box
8145 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
8149 VectorCopy(eye, start);
8150 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
8151 if (model->brush.TraceLineOfSight(model, start, end))
8154 // try various random positions
8155 for (i = 0;i < numsamples;i++)
8157 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
8158 if (model->brush.TraceLineOfSight(model, start, end))
8166 static void R_View_UpdateEntityVisible (void)
8171 entity_render_t *ent;
8173 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8174 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8175 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
8176 : RENDER_EXTERIORMODEL;
8177 if (!r_drawviewmodel.integer)
8178 renderimask |= RENDER_VIEWMODEL;
8179 if (!r_drawexteriormodel.integer)
8180 renderimask |= RENDER_EXTERIORMODEL;
8181 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
8183 // worldmodel can check visibility
8184 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
8185 for (i = 0;i < r_refdef.scene.numentities;i++)
8187 ent = r_refdef.scene.entities[i];
8188 if (!(ent->flags & renderimask))
8189 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)))
8190 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))
8191 r_refdef.viewcache.entityvisible[i] = true;
8193 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
8194 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
8196 for (i = 0;i < r_refdef.scene.numentities;i++)
8198 ent = r_refdef.scene.entities[i];
8199 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
8201 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
8203 continue; // temp entities do pvs only
8204 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
8205 ent->last_trace_visibility = realtime;
8206 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
8207 r_refdef.viewcache.entityvisible[i] = 0;
8214 // no worldmodel or it can't check visibility
8215 for (i = 0;i < r_refdef.scene.numentities;i++)
8217 ent = r_refdef.scene.entities[i];
8218 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));
8223 /// only used if skyrendermasked, and normally returns false
8224 int R_DrawBrushModelsSky (void)
8227 entity_render_t *ent;
8230 for (i = 0;i < r_refdef.scene.numentities;i++)
8232 if (!r_refdef.viewcache.entityvisible[i])
8234 ent = r_refdef.scene.entities[i];
8235 if (!ent->model || !ent->model->DrawSky)
8237 ent->model->DrawSky(ent);
8243 static void R_DrawNoModel(entity_render_t *ent);
8244 static void R_DrawModels(void)
8247 entity_render_t *ent;
8249 for (i = 0;i < r_refdef.scene.numentities;i++)
8251 if (!r_refdef.viewcache.entityvisible[i])
8253 ent = r_refdef.scene.entities[i];
8254 r_refdef.stats.entities++;
8255 if (ent->model && ent->model->Draw != NULL)
8256 ent->model->Draw(ent);
8262 static void R_DrawModelsDepth(void)
8265 entity_render_t *ent;
8267 for (i = 0;i < r_refdef.scene.numentities;i++)
8269 if (!r_refdef.viewcache.entityvisible[i])
8271 ent = r_refdef.scene.entities[i];
8272 if (ent->model && ent->model->DrawDepth != NULL)
8273 ent->model->DrawDepth(ent);
8277 static void R_DrawModelsDebug(void)
8280 entity_render_t *ent;
8282 for (i = 0;i < r_refdef.scene.numentities;i++)
8284 if (!r_refdef.viewcache.entityvisible[i])
8286 ent = r_refdef.scene.entities[i];
8287 if (ent->model && ent->model->DrawDebug != NULL)
8288 ent->model->DrawDebug(ent);
8292 static void R_DrawModelsAddWaterPlanes(void)
8295 entity_render_t *ent;
8297 for (i = 0;i < r_refdef.scene.numentities;i++)
8299 if (!r_refdef.viewcache.entityvisible[i])
8301 ent = r_refdef.scene.entities[i];
8302 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
8303 ent->model->DrawAddWaterPlanes(ent);
8307 static void R_View_SetFrustum(const int *scissor)
8310 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
8311 vec3_t forward, left, up, origin, v;
8315 // flipped x coordinates (because x points left here)
8316 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8317 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8319 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
8320 switch(vid.renderpath)
8322 case RENDERPATH_D3D9:
8323 case RENDERPATH_D3D10:
8324 case RENDERPATH_D3D11:
8325 case RENDERPATH_SOFT:
8326 // non-flipped y coordinates
8327 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8328 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8330 case RENDERPATH_GL11:
8331 case RENDERPATH_GL13:
8332 case RENDERPATH_GL20:
8333 case RENDERPATH_CGGL:
8334 // non-flipped y coordinates
8335 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8336 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8341 // we can't trust r_refdef.view.forward and friends in reflected scenes
8342 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
8345 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
8346 r_refdef.view.frustum[0].normal[1] = 0 - 0;
8347 r_refdef.view.frustum[0].normal[2] = -1 - 0;
8348 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
8349 r_refdef.view.frustum[1].normal[1] = 0 + 0;
8350 r_refdef.view.frustum[1].normal[2] = -1 + 0;
8351 r_refdef.view.frustum[2].normal[0] = 0 - 0;
8352 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
8353 r_refdef.view.frustum[2].normal[2] = -1 - 0;
8354 r_refdef.view.frustum[3].normal[0] = 0 + 0;
8355 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
8356 r_refdef.view.frustum[3].normal[2] = -1 + 0;
8360 zNear = r_refdef.nearclip;
8361 nudge = 1.0 - 1.0 / (1<<23);
8362 r_refdef.view.frustum[4].normal[0] = 0 - 0;
8363 r_refdef.view.frustum[4].normal[1] = 0 - 0;
8364 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
8365 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
8366 r_refdef.view.frustum[5].normal[0] = 0 + 0;
8367 r_refdef.view.frustum[5].normal[1] = 0 + 0;
8368 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
8369 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
8375 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8376 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8377 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8378 r_refdef.view.frustum[0].dist = m[15] - m[12];
8380 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8381 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8382 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8383 r_refdef.view.frustum[1].dist = m[15] + m[12];
8385 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8386 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8387 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8388 r_refdef.view.frustum[2].dist = m[15] - m[13];
8390 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8391 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8392 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8393 r_refdef.view.frustum[3].dist = m[15] + m[13];
8395 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8396 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8397 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8398 r_refdef.view.frustum[4].dist = m[15] - m[14];
8400 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8401 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8402 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8403 r_refdef.view.frustum[5].dist = m[15] + m[14];
8406 if (r_refdef.view.useperspective)
8408 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8409 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]);
8410 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]);
8411 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]);
8412 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]);
8414 // then the normals from the corners relative to origin
8415 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
8416 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
8417 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
8418 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
8420 // in a NORMAL view, forward cross left == up
8421 // in a REFLECTED view, forward cross left == down
8422 // so our cross products above need to be adjusted for a left handed coordinate system
8423 CrossProduct(forward, left, v);
8424 if(DotProduct(v, up) < 0)
8426 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
8427 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
8428 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
8429 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
8432 // Leaving those out was a mistake, those were in the old code, and they
8433 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8434 // I couldn't reproduce it after adding those normalizations. --blub
8435 VectorNormalize(r_refdef.view.frustum[0].normal);
8436 VectorNormalize(r_refdef.view.frustum[1].normal);
8437 VectorNormalize(r_refdef.view.frustum[2].normal);
8438 VectorNormalize(r_refdef.view.frustum[3].normal);
8440 // make the corners absolute
8441 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
8442 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
8443 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
8444 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
8447 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8449 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8450 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8451 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8452 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8453 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8457 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8458 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8459 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8460 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8461 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8462 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8463 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8464 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8465 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8466 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8468 r_refdef.view.numfrustumplanes = 5;
8470 if (r_refdef.view.useclipplane)
8472 r_refdef.view.numfrustumplanes = 6;
8473 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8476 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8477 PlaneClassify(r_refdef.view.frustum + i);
8479 // LordHavoc: note to all quake engine coders, Quake had a special case
8480 // for 90 degrees which assumed a square view (wrong), so I removed it,
8481 // Quake2 has it disabled as well.
8483 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8484 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8485 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8486 //PlaneClassify(&frustum[0]);
8488 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8489 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8490 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8491 //PlaneClassify(&frustum[1]);
8493 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8494 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8495 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8496 //PlaneClassify(&frustum[2]);
8498 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8499 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8500 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8501 //PlaneClassify(&frustum[3]);
8504 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8505 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8506 //PlaneClassify(&frustum[4]);
8509 void R_View_UpdateWithScissor(const int *myscissor)
8511 R_Main_ResizeViewCache();
8512 R_View_SetFrustum(myscissor);
8513 R_View_WorldVisibility(r_refdef.view.useclipplane);
8514 R_View_UpdateEntityVisible();
8515 R_View_UpdateEntityLighting();
8518 void R_View_Update(void)
8520 R_Main_ResizeViewCache();
8521 R_View_SetFrustum(NULL);
8522 R_View_WorldVisibility(r_refdef.view.useclipplane);
8523 R_View_UpdateEntityVisible();
8524 R_View_UpdateEntityLighting();
8527 void R_SetupView(qboolean allowwaterclippingplane)
8529 const float *customclipplane = NULL;
8531 if (r_refdef.view.useclipplane && allowwaterclippingplane)
8533 // LordHavoc: couldn't figure out how to make this approach the
8534 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8535 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8536 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8537 dist = r_refdef.view.clipplane.dist;
8538 plane[0] = r_refdef.view.clipplane.normal[0];
8539 plane[1] = r_refdef.view.clipplane.normal[1];
8540 plane[2] = r_refdef.view.clipplane.normal[2];
8542 customclipplane = plane;
8545 if (!r_refdef.view.useperspective)
8546 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);
8547 else if (vid.stencil && r_useinfinitefarclip.integer)
8548 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);
8550 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);
8551 R_SetViewport(&r_refdef.view.viewport);
8554 void R_EntityMatrix(const matrix4x4_t *matrix)
8556 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8558 gl_modelmatrixchanged = false;
8559 gl_modelmatrix = *matrix;
8560 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8561 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8562 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8563 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8565 switch(vid.renderpath)
8567 case RENDERPATH_D3D9:
8569 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8570 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8573 case RENDERPATH_D3D10:
8574 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8576 case RENDERPATH_D3D11:
8577 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8579 case RENDERPATH_GL20:
8580 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8581 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8582 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8584 case RENDERPATH_CGGL:
8587 if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8588 if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8589 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8592 case RENDERPATH_GL13:
8593 case RENDERPATH_GL11:
8594 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8596 case RENDERPATH_SOFT:
8597 DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
8598 DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
8604 void R_ResetViewRendering2D(void)
8606 r_viewport_t viewport;
8609 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8610 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);
8611 R_SetViewport(&viewport);
8612 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8613 GL_Color(1, 1, 1, 1);
8614 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8615 GL_BlendFunc(GL_ONE, GL_ZERO);
8616 GL_AlphaTest(false);
8617 GL_ScissorTest(false);
8618 GL_DepthMask(false);
8619 GL_DepthRange(0, 1);
8620 GL_DepthTest(false);
8621 GL_DepthFunc(GL_LEQUAL);
8622 R_EntityMatrix(&identitymatrix);
8623 R_Mesh_ResetTextureState();
8624 GL_PolygonOffset(0, 0);
8625 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8626 switch(vid.renderpath)
8628 case RENDERPATH_GL11:
8629 case RENDERPATH_GL13:
8630 case RENDERPATH_GL20:
8631 case RENDERPATH_CGGL:
8632 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8634 case RENDERPATH_D3D9:
8635 case RENDERPATH_D3D10:
8636 case RENDERPATH_D3D11:
8637 case RENDERPATH_SOFT:
8640 GL_CullFace(GL_NONE);
8643 void R_ResetViewRendering3D(void)
8648 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8649 GL_Color(1, 1, 1, 1);
8650 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8651 GL_BlendFunc(GL_ONE, GL_ZERO);
8652 GL_AlphaTest(false);
8653 GL_ScissorTest(true);
8655 GL_DepthRange(0, 1);
8657 GL_DepthFunc(GL_LEQUAL);
8658 R_EntityMatrix(&identitymatrix);
8659 R_Mesh_ResetTextureState();
8660 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8661 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8662 switch(vid.renderpath)
8664 case RENDERPATH_GL11:
8665 case RENDERPATH_GL13:
8666 case RENDERPATH_GL20:
8667 case RENDERPATH_CGGL:
8668 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8670 case RENDERPATH_D3D9:
8671 case RENDERPATH_D3D10:
8672 case RENDERPATH_D3D11:
8673 case RENDERPATH_SOFT:
8676 GL_CullFace(r_refdef.view.cullface_back);
8681 R_RenderView_UpdateViewVectors
8684 static void R_RenderView_UpdateViewVectors(void)
8686 // break apart the view matrix into vectors for various purposes
8687 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8688 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8689 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8690 VectorNegate(r_refdef.view.left, r_refdef.view.right);
8691 // make an inverted copy of the view matrix for tracking sprites
8692 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8695 void R_RenderScene(void);
8696 void R_RenderWaterPlanes(void);
8698 static void R_Water_StartFrame(void)
8701 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8702 r_waterstate_waterplane_t *p;
8704 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8707 switch(vid.renderpath)
8709 case RENDERPATH_GL20:
8710 case RENDERPATH_CGGL:
8711 case RENDERPATH_D3D9:
8712 case RENDERPATH_D3D10:
8713 case RENDERPATH_D3D11:
8714 case RENDERPATH_SOFT:
8716 case RENDERPATH_GL13:
8717 case RENDERPATH_GL11:
8721 // set waterwidth and waterheight to the water resolution that will be
8722 // used (often less than the screen resolution for faster rendering)
8723 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8724 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8726 // calculate desired texture sizes
8727 // can't use water if the card does not support the texture size
8728 if (!r_water.integer || r_showsurfaces.integer)
8729 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8730 else if (vid.support.arb_texture_non_power_of_two)
8732 texturewidth = waterwidth;
8733 textureheight = waterheight;
8734 camerawidth = waterwidth;
8735 cameraheight = waterheight;
8739 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
8740 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
8741 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
8742 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
8745 // allocate textures as needed
8746 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8748 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8749 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8751 if (p->texture_refraction)
8752 R_FreeTexture(p->texture_refraction);
8753 p->texture_refraction = NULL;
8754 if (p->texture_reflection)
8755 R_FreeTexture(p->texture_reflection);
8756 p->texture_reflection = NULL;
8757 if (p->texture_camera)
8758 R_FreeTexture(p->texture_camera);
8759 p->texture_camera = NULL;
8761 memset(&r_waterstate, 0, sizeof(r_waterstate));
8762 r_waterstate.texturewidth = texturewidth;
8763 r_waterstate.textureheight = textureheight;
8764 r_waterstate.camerawidth = camerawidth;
8765 r_waterstate.cameraheight = cameraheight;
8768 if (r_waterstate.texturewidth)
8770 r_waterstate.enabled = true;
8772 // when doing a reduced render (HDR) we want to use a smaller area
8773 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8774 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8776 // set up variables that will be used in shader setup
8777 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8778 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8779 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8780 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8783 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8784 r_waterstate.numwaterplanes = 0;
8787 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8789 int triangleindex, planeindex;
8795 r_waterstate_waterplane_t *p;
8796 texture_t *t = R_GetCurrentTexture(surface->texture);
8798 // just use the first triangle with a valid normal for any decisions
8799 VectorClear(normal);
8800 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8802 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8803 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8804 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8805 TriangleNormal(vert[0], vert[1], vert[2], normal);
8806 if (VectorLength2(normal) >= 0.001)
8810 VectorCopy(normal, plane.normal);
8811 VectorNormalize(plane.normal);
8812 plane.dist = DotProduct(vert[0], plane.normal);
8813 PlaneClassify(&plane);
8814 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8816 // skip backfaces (except if nocullface is set)
8817 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8819 VectorNegate(plane.normal, plane.normal);
8821 PlaneClassify(&plane);
8825 // find a matching plane if there is one
8826 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8827 if(p->camera_entity == t->camera_entity)
8828 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8830 if (planeindex >= r_waterstate.maxwaterplanes)
8831 return; // nothing we can do, out of planes
8833 // if this triangle does not fit any known plane rendered this frame, add one
8834 if (planeindex >= r_waterstate.numwaterplanes)
8836 // store the new plane
8837 r_waterstate.numwaterplanes++;
8839 // clear materialflags and pvs
8840 p->materialflags = 0;
8841 p->pvsvalid = false;
8842 p->camera_entity = t->camera_entity;
8843 VectorCopy(surface->mins, p->mins);
8844 VectorCopy(surface->maxs, p->maxs);
8849 p->mins[0] = min(p->mins[0], surface->mins[0]);
8850 p->mins[1] = min(p->mins[1], surface->mins[1]);
8851 p->mins[2] = min(p->mins[2], surface->mins[2]);
8852 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8853 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8854 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8856 // merge this surface's materialflags into the waterplane
8857 p->materialflags |= t->currentmaterialflags;
8858 if(!(p->materialflags & MATERIALFLAG_CAMERA))
8860 // merge this surface's PVS into the waterplane
8861 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8862 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8863 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8865 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8871 static void R_Water_ProcessPlanes(void)
8874 r_refdef_view_t originalview;
8875 r_refdef_view_t myview;
8877 r_waterstate_waterplane_t *p;
8880 originalview = r_refdef.view;
8882 // make sure enough textures are allocated
8883 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8885 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8887 if (!p->texture_refraction)
8888 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);
8889 if (!p->texture_refraction)
8892 else if (p->materialflags & MATERIALFLAG_CAMERA)
8894 if (!p->texture_camera)
8895 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);
8896 if (!p->texture_camera)
8900 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8902 if (!p->texture_reflection)
8903 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);
8904 if (!p->texture_reflection)
8910 r_refdef.view = originalview;
8911 r_refdef.view.showdebug = false;
8912 r_refdef.view.width = r_waterstate.waterwidth;
8913 r_refdef.view.height = r_waterstate.waterheight;
8914 r_refdef.view.useclipplane = true;
8915 myview = r_refdef.view;
8916 r_waterstate.renderingscene = true;
8917 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8919 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8921 r_refdef.view = myview;
8922 if(r_water_scissormode.integer)
8925 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8926 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8929 // render reflected scene and copy into texture
8930 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8931 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8932 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8933 r_refdef.view.clipplane = p->plane;
8935 // reverse the cullface settings for this render
8936 r_refdef.view.cullface_front = GL_FRONT;
8937 r_refdef.view.cullface_back = GL_BACK;
8938 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8940 r_refdef.view.usecustompvs = true;
8942 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8944 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8947 R_ResetViewRendering3D();
8948 R_ClearScreen(r_refdef.fogenabled);
8949 if(r_water_scissormode.integer & 2)
8950 R_View_UpdateWithScissor(myscissor);
8953 if(r_water_scissormode.integer & 1)
8954 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8957 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);
8960 // render the normal view scene and copy into texture
8961 // (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)
8962 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8964 r_refdef.view = myview;
8965 if(r_water_scissormode.integer)
8968 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8969 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8972 r_waterstate.renderingrefraction = true;
8974 r_refdef.view.clipplane = p->plane;
8975 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8976 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8978 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8980 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8981 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8982 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8983 R_RenderView_UpdateViewVectors();
8984 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8986 r_refdef.view.usecustompvs = true;
8987 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);
8991 PlaneClassify(&r_refdef.view.clipplane);
8993 R_ResetViewRendering3D();
8994 R_ClearScreen(r_refdef.fogenabled);
8995 if(r_water_scissormode.integer & 2)
8996 R_View_UpdateWithScissor(myscissor);
8999 if(r_water_scissormode.integer & 1)
9000 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
9003 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);
9004 r_waterstate.renderingrefraction = false;
9006 else if (p->materialflags & MATERIALFLAG_CAMERA)
9008 r_refdef.view = myview;
9010 r_refdef.view.clipplane = p->plane;
9011 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
9012 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
9014 r_refdef.view.width = r_waterstate.camerawidth;
9015 r_refdef.view.height = r_waterstate.cameraheight;
9016 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
9017 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
9019 if(p->camera_entity)
9021 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
9022 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
9025 // note: all of the view is used for displaying... so
9026 // there is no use in scissoring
9028 // reverse the cullface settings for this render
9029 r_refdef.view.cullface_front = GL_FRONT;
9030 r_refdef.view.cullface_back = GL_BACK;
9031 // also reverse the view matrix
9032 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
9033 R_RenderView_UpdateViewVectors();
9034 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
9036 r_refdef.view.usecustompvs = true;
9037 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);
9040 // camera needs no clipplane
9041 r_refdef.view.useclipplane = false;
9043 PlaneClassify(&r_refdef.view.clipplane);
9045 R_ResetViewRendering3D();
9046 R_ClearScreen(r_refdef.fogenabled);
9050 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);
9051 r_waterstate.renderingrefraction = false;
9055 r_waterstate.renderingscene = false;
9056 r_refdef.view = originalview;
9057 R_ResetViewRendering3D();
9058 R_ClearScreen(r_refdef.fogenabled);
9062 r_refdef.view = originalview;
9063 r_waterstate.renderingscene = false;
9064 Cvar_SetValueQuick(&r_water, 0);
9065 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
9069 void R_Bloom_StartFrame(void)
9071 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
9073 switch(vid.renderpath)
9075 case RENDERPATH_GL20:
9076 case RENDERPATH_CGGL:
9077 case RENDERPATH_D3D9:
9078 case RENDERPATH_D3D10:
9079 case RENDERPATH_D3D11:
9080 case RENDERPATH_SOFT:
9082 case RENDERPATH_GL13:
9083 case RENDERPATH_GL11:
9087 // set bloomwidth and bloomheight to the bloom resolution that will be
9088 // used (often less than the screen resolution for faster rendering)
9089 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
9090 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
9091 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
9092 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
9093 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
9095 // calculate desired texture sizes
9096 if (vid.support.arb_texture_non_power_of_two)
9098 screentexturewidth = r_refdef.view.width;
9099 screentextureheight = r_refdef.view.height;
9100 bloomtexturewidth = r_bloomstate.bloomwidth;
9101 bloomtextureheight = r_bloomstate.bloomheight;
9105 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
9106 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
9107 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
9108 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
9111 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))
9113 Cvar_SetValueQuick(&r_hdr, 0);
9114 Cvar_SetValueQuick(&r_bloom, 0);
9115 Cvar_SetValueQuick(&r_motionblur, 0);
9116 Cvar_SetValueQuick(&r_damageblur, 0);
9119 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)))
9120 screentexturewidth = screentextureheight = 0;
9121 if (!r_hdr.integer && !r_bloom.integer)
9122 bloomtexturewidth = bloomtextureheight = 0;
9124 // allocate textures as needed
9125 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
9127 if (r_bloomstate.texture_screen)
9128 R_FreeTexture(r_bloomstate.texture_screen);
9129 r_bloomstate.texture_screen = NULL;
9130 r_bloomstate.screentexturewidth = screentexturewidth;
9131 r_bloomstate.screentextureheight = screentextureheight;
9132 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
9133 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);
9135 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
9137 if (r_bloomstate.texture_bloom)
9138 R_FreeTexture(r_bloomstate.texture_bloom);
9139 r_bloomstate.texture_bloom = NULL;
9140 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
9141 r_bloomstate.bloomtextureheight = bloomtextureheight;
9142 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
9143 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);
9146 // when doing a reduced render (HDR) we want to use a smaller area
9147 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
9148 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
9149 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
9150 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
9151 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
9153 // set up a texcoord array for the full resolution screen image
9154 // (we have to keep this around to copy back during final render)
9155 r_bloomstate.screentexcoord2f[0] = 0;
9156 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
9157 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
9158 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
9159 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
9160 r_bloomstate.screentexcoord2f[5] = 0;
9161 r_bloomstate.screentexcoord2f[6] = 0;
9162 r_bloomstate.screentexcoord2f[7] = 0;
9164 // set up a texcoord array for the reduced resolution bloom image
9165 // (which will be additive blended over the screen image)
9166 r_bloomstate.bloomtexcoord2f[0] = 0;
9167 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9168 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9169 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9170 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9171 r_bloomstate.bloomtexcoord2f[5] = 0;
9172 r_bloomstate.bloomtexcoord2f[6] = 0;
9173 r_bloomstate.bloomtexcoord2f[7] = 0;
9175 switch(vid.renderpath)
9177 case RENDERPATH_GL11:
9178 case RENDERPATH_GL13:
9179 case RENDERPATH_GL20:
9180 case RENDERPATH_CGGL:
9181 case RENDERPATH_SOFT:
9183 case RENDERPATH_D3D9:
9184 case RENDERPATH_D3D10:
9185 case RENDERPATH_D3D11:
9188 for (i = 0;i < 4;i++)
9190 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
9191 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
9192 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
9193 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
9199 if (r_hdr.integer || r_bloom.integer)
9201 r_bloomstate.enabled = true;
9202 r_bloomstate.hdr = r_hdr.integer != 0;
9205 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);
9208 void R_Bloom_CopyBloomTexture(float colorscale)
9210 r_refdef.stats.bloom++;
9212 // scale down screen texture to the bloom texture size
9214 R_SetViewport(&r_bloomstate.viewport);
9215 GL_BlendFunc(GL_ONE, GL_ZERO);
9216 GL_Color(colorscale, colorscale, colorscale, 1);
9217 // 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...
9218 switch(vid.renderpath)
9220 case RENDERPATH_GL11:
9221 case RENDERPATH_GL13:
9222 case RENDERPATH_GL20:
9223 case RENDERPATH_CGGL:
9224 case RENDERPATH_SOFT:
9225 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9227 case RENDERPATH_D3D9:
9228 case RENDERPATH_D3D10:
9229 case RENDERPATH_D3D11:
9230 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9233 // TODO: do boxfilter scale-down in shader?
9234 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9235 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9236 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9238 // we now have a bloom image in the framebuffer
9239 // copy it into the bloom image texture for later processing
9240 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);
9241 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9244 void R_Bloom_CopyHDRTexture(void)
9246 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);
9247 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9250 void R_Bloom_MakeTexture(void)
9253 float xoffset, yoffset, r, brighten;
9255 r_refdef.stats.bloom++;
9257 R_ResetViewRendering2D();
9259 // we have a bloom image in the framebuffer
9261 R_SetViewport(&r_bloomstate.viewport);
9263 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
9266 r = bound(0, r_bloom_colorexponent.value / x, 1);
9267 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9269 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
9270 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9271 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9272 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9274 // copy the vertically blurred bloom view to a texture
9275 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);
9276 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9279 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
9280 brighten = r_bloom_brighten.value;
9282 brighten *= r_hdr_range.value;
9283 brighten = sqrt(brighten);
9285 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
9286 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9288 for (dir = 0;dir < 2;dir++)
9290 // blend on at multiple vertical offsets to achieve a vertical blur
9291 // TODO: do offset blends using GLSL
9292 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
9293 GL_BlendFunc(GL_ONE, GL_ZERO);
9294 for (x = -range;x <= range;x++)
9296 if (!dir){xoffset = 0;yoffset = x;}
9297 else {xoffset = x;yoffset = 0;}
9298 xoffset /= (float)r_bloomstate.bloomtexturewidth;
9299 yoffset /= (float)r_bloomstate.bloomtextureheight;
9300 // compute a texcoord array with the specified x and y offset
9301 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
9302 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9303 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9304 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9305 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9306 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
9307 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
9308 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
9309 // this r value looks like a 'dot' particle, fading sharply to
9310 // black at the edges
9311 // (probably not realistic but looks good enough)
9312 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
9313 //r = brighten/(range*2+1);
9314 r = brighten / (range * 2 + 1);
9316 r *= (1 - x*x/(float)(range*range));
9317 GL_Color(r, r, r, 1);
9318 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
9319 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9320 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9321 GL_BlendFunc(GL_ONE, GL_ONE);
9324 // copy the vertically blurred bloom view to a texture
9325 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);
9326 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9330 void R_HDR_RenderBloomTexture(void)
9332 int oldwidth, oldheight;
9333 float oldcolorscale;
9334 qboolean oldwaterstate;
9336 oldwaterstate = r_waterstate.enabled;
9337 oldcolorscale = r_refdef.view.colorscale;
9338 oldwidth = r_refdef.view.width;
9339 oldheight = r_refdef.view.height;
9340 r_refdef.view.width = r_bloomstate.bloomwidth;
9341 r_refdef.view.height = r_bloomstate.bloomheight;
9343 if(r_hdr.integer < 2)
9344 r_waterstate.enabled = false;
9346 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
9347 // TODO: add exposure compensation features
9348 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
9350 r_refdef.view.showdebug = false;
9351 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
9353 R_ResetViewRendering3D();
9355 R_ClearScreen(r_refdef.fogenabled);
9356 if (r_timereport_active)
9357 R_TimeReport("HDRclear");
9360 if (r_timereport_active)
9361 R_TimeReport("visibility");
9363 // only do secondary renders with HDR if r_hdr is 2 or higher
9364 r_waterstate.numwaterplanes = 0;
9365 if (r_waterstate.enabled)
9366 R_RenderWaterPlanes();
9368 r_refdef.view.showdebug = true;
9370 r_waterstate.numwaterplanes = 0;
9372 R_ResetViewRendering2D();
9374 R_Bloom_CopyHDRTexture();
9375 R_Bloom_MakeTexture();
9377 // restore the view settings
9378 r_waterstate.enabled = oldwaterstate;
9379 r_refdef.view.width = oldwidth;
9380 r_refdef.view.height = oldheight;
9381 r_refdef.view.colorscale = oldcolorscale;
9383 R_ResetViewRendering3D();
9385 R_ClearScreen(r_refdef.fogenabled);
9386 if (r_timereport_active)
9387 R_TimeReport("viewclear");
9390 static void R_BlendView(void)
9392 unsigned int permutation;
9393 float uservecs[4][4];
9395 switch (vid.renderpath)
9397 case RENDERPATH_GL20:
9398 case RENDERPATH_CGGL:
9399 case RENDERPATH_D3D9:
9400 case RENDERPATH_D3D10:
9401 case RENDERPATH_D3D11:
9402 case RENDERPATH_SOFT:
9404 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
9405 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
9406 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
9407 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
9408 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
9410 if (r_bloomstate.texture_screen)
9412 // make sure the buffer is available
9413 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
9415 R_ResetViewRendering2D();
9417 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
9419 // declare variables
9421 static float avgspeed;
9423 speed = VectorLength(cl.movement_velocity);
9425 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
9426 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
9428 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
9429 speed = bound(0, speed, 1);
9430 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
9432 // calculate values into a standard alpha
9433 cl.motionbluralpha = 1 - exp(-
9435 (r_motionblur.value * speed / 80)
9437 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
9440 max(0.0001, cl.time - cl.oldtime) // fps independent
9443 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
9444 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
9446 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
9448 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9449 GL_Color(1, 1, 1, cl.motionbluralpha);
9450 switch(vid.renderpath)
9452 case RENDERPATH_GL11:
9453 case RENDERPATH_GL13:
9454 case RENDERPATH_GL20:
9455 case RENDERPATH_CGGL:
9456 case RENDERPATH_SOFT:
9457 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9459 case RENDERPATH_D3D9:
9460 case RENDERPATH_D3D10:
9461 case RENDERPATH_D3D11:
9462 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9465 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9466 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9467 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9471 // copy view into the screen texture
9472 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);
9473 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9475 else if (!r_bloomstate.texture_bloom)
9477 // we may still have to do view tint...
9478 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9480 // apply a color tint to the whole view
9481 R_ResetViewRendering2D();
9482 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9483 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9484 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9485 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9486 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9488 break; // no screen processing, no bloom, skip it
9491 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9493 // render simple bloom effect
9494 // copy the screen and shrink it and darken it for the bloom process
9495 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9496 // make the bloom texture
9497 R_Bloom_MakeTexture();
9500 #if _MSC_VER >= 1400
9501 #define sscanf sscanf_s
9503 memset(uservecs, 0, sizeof(uservecs));
9504 if (r_glsl_postprocess_uservec1_enable.integer)
9505 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9506 if (r_glsl_postprocess_uservec2_enable.integer)
9507 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9508 if (r_glsl_postprocess_uservec3_enable.integer)
9509 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9510 if (r_glsl_postprocess_uservec4_enable.integer)
9511 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9513 R_ResetViewRendering2D();
9514 GL_Color(1, 1, 1, 1);
9515 GL_BlendFunc(GL_ONE, GL_ZERO);
9517 switch(vid.renderpath)
9519 case RENDERPATH_GL20:
9520 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9521 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9522 if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
9523 if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
9524 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
9525 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]);
9526 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9527 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]);
9528 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]);
9529 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]);
9530 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]);
9531 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
9532 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9533 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);
9535 case RENDERPATH_CGGL:
9537 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9538 R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9539 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_bloomstate.texture_screen);CHECKCGERROR
9540 if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_bloomstate.texture_bloom );CHECKCGERROR
9541 if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps );CHECKCGERROR
9542 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
9543 if (r_cg_permutation->fp_PixelSize ) cgGLSetParameter2f( r_cg_permutation->fp_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9544 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
9545 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
9546 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
9547 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
9548 if (r_cg_permutation->fp_Saturation ) cgGLSetParameter1f( r_cg_permutation->fp_Saturation , r_glsl_saturation.value);CHECKCGERROR
9549 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9550 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);
9553 case RENDERPATH_D3D9:
9555 // 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...
9556 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9557 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9558 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
9559 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
9560 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
9561 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9562 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9563 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9564 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9565 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9566 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9567 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
9568 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9569 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9572 case RENDERPATH_D3D10:
9573 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9575 case RENDERPATH_D3D11:
9576 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9578 case RENDERPATH_SOFT:
9579 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9580 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
9581 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
9582 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
9583 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
9584 DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9585 DPSOFTRAST_Uniform2fARB(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9586 DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9587 DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9588 DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9589 DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9590 DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
9591 DPSOFTRAST_Uniform2fARB(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9592 DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9597 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9598 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9600 case RENDERPATH_GL13:
9601 case RENDERPATH_GL11:
9602 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9604 // apply a color tint to the whole view
9605 R_ResetViewRendering2D();
9606 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9607 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9608 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9609 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9610 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9616 matrix4x4_t r_waterscrollmatrix;
9618 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9620 if (r_refdef.fog_density)
9622 r_refdef.fogcolor[0] = r_refdef.fog_red;
9623 r_refdef.fogcolor[1] = r_refdef.fog_green;
9624 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9626 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9627 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9628 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9629 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9633 VectorCopy(r_refdef.fogcolor, fogvec);
9634 // color.rgb *= ContrastBoost * SceneBrightness;
9635 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9636 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9637 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9638 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9643 void R_UpdateVariables(void)
9647 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9649 r_refdef.farclip = r_farclip_base.value;
9650 if (r_refdef.scene.worldmodel)
9651 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9652 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9654 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9655 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9656 r_refdef.polygonfactor = 0;
9657 r_refdef.polygonoffset = 0;
9658 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9659 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9661 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9662 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9663 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
9664 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9665 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9666 if (FAKELIGHT_ENABLED)
9668 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
9670 if (r_showsurfaces.integer)
9672 r_refdef.scene.rtworld = false;
9673 r_refdef.scene.rtworldshadows = false;
9674 r_refdef.scene.rtdlight = false;
9675 r_refdef.scene.rtdlightshadows = false;
9676 r_refdef.lightmapintensity = 0;
9679 if (gamemode == GAME_NEHAHRA)
9681 if (gl_fogenable.integer)
9683 r_refdef.oldgl_fogenable = true;
9684 r_refdef.fog_density = gl_fogdensity.value;
9685 r_refdef.fog_red = gl_fogred.value;
9686 r_refdef.fog_green = gl_foggreen.value;
9687 r_refdef.fog_blue = gl_fogblue.value;
9688 r_refdef.fog_alpha = 1;
9689 r_refdef.fog_start = 0;
9690 r_refdef.fog_end = gl_skyclip.value;
9691 r_refdef.fog_height = 1<<30;
9692 r_refdef.fog_fadedepth = 128;
9694 else if (r_refdef.oldgl_fogenable)
9696 r_refdef.oldgl_fogenable = false;
9697 r_refdef.fog_density = 0;
9698 r_refdef.fog_red = 0;
9699 r_refdef.fog_green = 0;
9700 r_refdef.fog_blue = 0;
9701 r_refdef.fog_alpha = 0;
9702 r_refdef.fog_start = 0;
9703 r_refdef.fog_end = 0;
9704 r_refdef.fog_height = 1<<30;
9705 r_refdef.fog_fadedepth = 128;
9709 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9710 r_refdef.fog_start = max(0, r_refdef.fog_start);
9711 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9713 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9715 if (r_refdef.fog_density && r_drawfog.integer)
9717 r_refdef.fogenabled = true;
9718 // this is the point where the fog reaches 0.9986 alpha, which we
9719 // consider a good enough cutoff point for the texture
9720 // (0.9986 * 256 == 255.6)
9721 if (r_fog_exp2.integer)
9722 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9724 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9725 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9726 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9727 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9728 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9729 R_BuildFogHeightTexture();
9730 // fog color was already set
9731 // update the fog texture
9732 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)
9733 R_BuildFogTexture();
9734 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9735 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9738 r_refdef.fogenabled = false;
9740 switch(vid.renderpath)
9742 case RENDERPATH_GL20:
9743 case RENDERPATH_CGGL:
9744 case RENDERPATH_D3D9:
9745 case RENDERPATH_D3D10:
9746 case RENDERPATH_D3D11:
9747 case RENDERPATH_SOFT:
9748 if(v_glslgamma.integer && !vid_gammatables_trivial)
9750 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9752 // build GLSL gamma texture
9753 #define RAMPWIDTH 256
9754 unsigned short ramp[RAMPWIDTH * 3];
9755 unsigned char rampbgr[RAMPWIDTH][4];
9758 r_texture_gammaramps_serial = vid_gammatables_serial;
9760 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9761 for(i = 0; i < RAMPWIDTH; ++i)
9763 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9764 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9765 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9768 if (r_texture_gammaramps)
9770 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9774 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9780 // remove GLSL gamma texture
9783 case RENDERPATH_GL13:
9784 case RENDERPATH_GL11:
9789 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9790 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9796 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9797 if( scenetype != r_currentscenetype ) {
9798 // store the old scenetype
9799 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9800 r_currentscenetype = scenetype;
9801 // move in the new scene
9802 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9811 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9813 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9814 if( scenetype == r_currentscenetype ) {
9815 return &r_refdef.scene;
9817 return &r_scenes_store[ scenetype ];
9826 void R_RenderView(void)
9828 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
9829 if (r_timereport_active)
9830 R_TimeReport("start");
9831 r_textureframe++; // used only by R_GetCurrentTexture
9832 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9834 if(R_CompileShader_CheckStaticParms())
9837 if (!r_drawentities.integer)
9838 r_refdef.scene.numentities = 0;
9840 R_AnimCache_ClearCache();
9841 R_FrameData_NewFrame();
9843 /* adjust for stereo display */
9844 if(R_Stereo_Active())
9846 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);
9847 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
9850 if (r_refdef.view.isoverlay)
9852 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9853 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9854 R_TimeReport("depthclear");
9856 r_refdef.view.showdebug = false;
9858 r_waterstate.enabled = false;
9859 r_waterstate.numwaterplanes = 0;
9863 r_refdef.view.matrix = originalmatrix;
9869 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9871 r_refdef.view.matrix = originalmatrix;
9872 return; //Host_Error ("R_RenderView: NULL worldmodel");
9875 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9877 R_RenderView_UpdateViewVectors();
9879 R_Shadow_UpdateWorldLightSelection();
9881 R_Bloom_StartFrame();
9882 R_Water_StartFrame();
9885 if (r_timereport_active)
9886 R_TimeReport("viewsetup");
9888 R_ResetViewRendering3D();
9890 if (r_refdef.view.clear || r_refdef.fogenabled)
9892 R_ClearScreen(r_refdef.fogenabled);
9893 if (r_timereport_active)
9894 R_TimeReport("viewclear");
9896 r_refdef.view.clear = true;
9898 // this produces a bloom texture to be used in R_BlendView() later
9899 if (r_hdr.integer && r_bloomstate.bloomwidth)
9901 R_HDR_RenderBloomTexture();
9902 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9903 r_textureframe++; // used only by R_GetCurrentTexture
9906 r_refdef.view.showdebug = true;
9909 if (r_timereport_active)
9910 R_TimeReport("visibility");
9912 r_waterstate.numwaterplanes = 0;
9913 if (r_waterstate.enabled)
9914 R_RenderWaterPlanes();
9917 r_waterstate.numwaterplanes = 0;
9920 if (r_timereport_active)
9921 R_TimeReport("blendview");
9923 GL_Scissor(0, 0, vid.width, vid.height);
9924 GL_ScissorTest(false);
9926 r_refdef.view.matrix = originalmatrix;
9931 void R_RenderWaterPlanes(void)
9933 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9935 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9936 if (r_timereport_active)
9937 R_TimeReport("waterworld");
9940 // don't let sound skip if going slow
9941 if (r_refdef.scene.extraupdate)
9944 R_DrawModelsAddWaterPlanes();
9945 if (r_timereport_active)
9946 R_TimeReport("watermodels");
9948 if (r_waterstate.numwaterplanes)
9950 R_Water_ProcessPlanes();
9951 if (r_timereport_active)
9952 R_TimeReport("waterscenes");
9956 extern void R_DrawLightningBeams (void);
9957 extern void VM_CL_AddPolygonsToMeshQueue (void);
9958 extern void R_DrawPortals (void);
9959 extern cvar_t cl_locs_show;
9960 static void R_DrawLocs(void);
9961 static void R_DrawEntityBBoxes(void);
9962 static void R_DrawModelDecals(void);
9963 extern void R_DrawModelShadows(void);
9964 extern void R_DrawModelShadowMaps(void);
9965 extern cvar_t cl_decals_newsystem;
9966 extern qboolean r_shadow_usingdeferredprepass;
9967 void R_RenderScene(void)
9969 qboolean shadowmapping = false;
9971 if (r_timereport_active)
9972 R_TimeReport("beginscene");
9974 r_refdef.stats.renders++;
9978 // don't let sound skip if going slow
9979 if (r_refdef.scene.extraupdate)
9982 R_MeshQueue_BeginScene();
9986 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);
9988 if (r_timereport_active)
9989 R_TimeReport("skystartframe");
9991 if (cl.csqc_vidvars.drawworld)
9993 // don't let sound skip if going slow
9994 if (r_refdef.scene.extraupdate)
9997 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9999 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
10000 if (r_timereport_active)
10001 R_TimeReport("worldsky");
10004 if (R_DrawBrushModelsSky() && r_timereport_active)
10005 R_TimeReport("bmodelsky");
10007 if (skyrendermasked && skyrenderlater)
10009 // we have to force off the water clipping plane while rendering sky
10010 R_SetupView(false);
10013 if (r_timereport_active)
10014 R_TimeReport("sky");
10018 R_AnimCache_CacheVisibleEntities();
10019 if (r_timereport_active)
10020 R_TimeReport("animation");
10022 R_Shadow_PrepareLights();
10023 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
10024 R_Shadow_PrepareModelShadows();
10025 if (r_timereport_active)
10026 R_TimeReport("preparelights");
10028 if (R_Shadow_ShadowMappingEnabled())
10029 shadowmapping = true;
10031 if (r_shadow_usingdeferredprepass)
10032 R_Shadow_DrawPrepass();
10034 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
10036 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
10037 if (r_timereport_active)
10038 R_TimeReport("worlddepth");
10040 if (r_depthfirst.integer >= 2)
10042 R_DrawModelsDepth();
10043 if (r_timereport_active)
10044 R_TimeReport("modeldepth");
10047 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
10049 R_DrawModelShadowMaps();
10050 R_ResetViewRendering3D();
10051 // don't let sound skip if going slow
10052 if (r_refdef.scene.extraupdate)
10056 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
10058 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
10059 if (r_timereport_active)
10060 R_TimeReport("world");
10063 // don't let sound skip if going slow
10064 if (r_refdef.scene.extraupdate)
10068 if (r_timereport_active)
10069 R_TimeReport("models");
10071 // don't let sound skip if going slow
10072 if (r_refdef.scene.extraupdate)
10075 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
10077 R_DrawModelShadows();
10078 R_ResetViewRendering3D();
10079 // don't let sound skip if going slow
10080 if (r_refdef.scene.extraupdate)
10084 if (!r_shadow_usingdeferredprepass)
10086 R_Shadow_DrawLights();
10087 if (r_timereport_active)
10088 R_TimeReport("rtlights");
10091 // don't let sound skip if going slow
10092 if (r_refdef.scene.extraupdate)
10095 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
10097 R_DrawModelShadows();
10098 R_ResetViewRendering3D();
10099 // don't let sound skip if going slow
10100 if (r_refdef.scene.extraupdate)
10104 if (cl.csqc_vidvars.drawworld)
10106 if (cl_decals_newsystem.integer)
10108 R_DrawModelDecals();
10109 if (r_timereport_active)
10110 R_TimeReport("modeldecals");
10115 if (r_timereport_active)
10116 R_TimeReport("decals");
10120 if (r_timereport_active)
10121 R_TimeReport("particles");
10123 R_DrawExplosions();
10124 if (r_timereport_active)
10125 R_TimeReport("explosions");
10127 R_DrawLightningBeams();
10128 if (r_timereport_active)
10129 R_TimeReport("lightning");
10132 VM_CL_AddPolygonsToMeshQueue();
10134 if (r_refdef.view.showdebug)
10136 if (cl_locs_show.integer)
10139 if (r_timereport_active)
10140 R_TimeReport("showlocs");
10143 if (r_drawportals.integer)
10146 if (r_timereport_active)
10147 R_TimeReport("portals");
10150 if (r_showbboxes.value > 0)
10152 R_DrawEntityBBoxes();
10153 if (r_timereport_active)
10154 R_TimeReport("bboxes");
10158 R_MeshQueue_RenderTransparent();
10159 if (r_timereport_active)
10160 R_TimeReport("drawtrans");
10162 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))
10164 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
10165 if (r_timereport_active)
10166 R_TimeReport("worlddebug");
10167 R_DrawModelsDebug();
10168 if (r_timereport_active)
10169 R_TimeReport("modeldebug");
10172 if (cl.csqc_vidvars.drawworld)
10174 R_Shadow_DrawCoronas();
10175 if (r_timereport_active)
10176 R_TimeReport("coronas");
10181 GL_DepthTest(false);
10182 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10183 GL_Color(1, 1, 1, 1);
10184 qglBegin(GL_POLYGON);
10185 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
10186 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
10187 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
10188 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
10190 qglBegin(GL_POLYGON);
10191 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]);
10192 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]);
10193 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]);
10194 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]);
10196 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10200 // don't let sound skip if going slow
10201 if (r_refdef.scene.extraupdate)
10204 R_ResetViewRendering2D();
10207 static const unsigned short bboxelements[36] =
10217 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
10220 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
10222 RSurf_ActiveWorldEntity();
10224 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10225 GL_DepthMask(false);
10226 GL_DepthRange(0, 1);
10227 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10228 // R_Mesh_ResetTextureState();
10230 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
10231 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
10232 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
10233 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
10234 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
10235 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
10236 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
10237 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
10238 R_FillColors(color4f, 8, cr, cg, cb, ca);
10239 if (r_refdef.fogenabled)
10241 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
10243 f1 = RSurf_FogVertex(v);
10245 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
10246 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
10247 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
10250 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
10251 R_Mesh_ResetTextureState();
10252 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10253 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
10256 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10260 prvm_edict_t *edict;
10261 prvm_prog_t *prog_save = prog;
10263 // this function draws bounding boxes of server entities
10267 GL_CullFace(GL_NONE);
10268 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10272 for (i = 0;i < numsurfaces;i++)
10274 edict = PRVM_EDICT_NUM(surfacelist[i]);
10275 switch ((int)edict->fields.server->solid)
10277 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
10278 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
10279 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
10280 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
10281 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
10282 default: Vector4Set(color, 0, 0, 0, 0.50);break;
10284 color[3] *= r_showbboxes.value;
10285 color[3] = bound(0, color[3], 1);
10286 GL_DepthTest(!r_showdisabledepthtest.integer);
10287 GL_CullFace(r_refdef.view.cullface_front);
10288 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
10294 static void R_DrawEntityBBoxes(void)
10297 prvm_edict_t *edict;
10299 prvm_prog_t *prog_save = prog;
10301 // this function draws bounding boxes of server entities
10307 for (i = 0;i < prog->num_edicts;i++)
10309 edict = PRVM_EDICT_NUM(i);
10310 if (edict->priv.server->free)
10312 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
10313 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
10315 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
10317 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
10318 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
10324 static const int nomodelelement3i[24] =
10336 static const unsigned short nomodelelement3s[24] =
10348 static const float nomodelvertex3f[6*3] =
10358 static const float nomodelcolor4f[6*4] =
10360 0.0f, 0.0f, 0.5f, 1.0f,
10361 0.0f, 0.0f, 0.5f, 1.0f,
10362 0.0f, 0.5f, 0.0f, 1.0f,
10363 0.0f, 0.5f, 0.0f, 1.0f,
10364 0.5f, 0.0f, 0.0f, 1.0f,
10365 0.5f, 0.0f, 0.0f, 1.0f
10368 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10372 float color4f[6*4];
10374 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);
10376 // this is only called once per entity so numsurfaces is always 1, and
10377 // surfacelist is always {0}, so this code does not handle batches
10379 if (rsurface.ent_flags & RENDER_ADDITIVE)
10381 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
10382 GL_DepthMask(false);
10384 else if (rsurface.colormod[3] < 1)
10386 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10387 GL_DepthMask(false);
10391 GL_BlendFunc(GL_ONE, GL_ZERO);
10392 GL_DepthMask(true);
10394 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
10395 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
10396 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
10397 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
10398 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
10399 for (i = 0, c = color4f;i < 6;i++, c += 4)
10401 c[0] *= rsurface.colormod[0];
10402 c[1] *= rsurface.colormod[1];
10403 c[2] *= rsurface.colormod[2];
10404 c[3] *= rsurface.colormod[3];
10406 if (r_refdef.fogenabled)
10408 for (i = 0, c = color4f;i < 6;i++, c += 4)
10410 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
10412 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
10413 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
10414 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
10417 // R_Mesh_ResetTextureState();
10418 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10419 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
10420 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
10423 void R_DrawNoModel(entity_render_t *ent)
10426 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
10427 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
10428 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
10430 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
10433 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
10435 vec3_t right1, right2, diff, normal;
10437 VectorSubtract (org2, org1, normal);
10439 // calculate 'right' vector for start
10440 VectorSubtract (r_refdef.view.origin, org1, diff);
10441 CrossProduct (normal, diff, right1);
10442 VectorNormalize (right1);
10444 // calculate 'right' vector for end
10445 VectorSubtract (r_refdef.view.origin, org2, diff);
10446 CrossProduct (normal, diff, right2);
10447 VectorNormalize (right2);
10449 vert[ 0] = org1[0] + width * right1[0];
10450 vert[ 1] = org1[1] + width * right1[1];
10451 vert[ 2] = org1[2] + width * right1[2];
10452 vert[ 3] = org1[0] - width * right1[0];
10453 vert[ 4] = org1[1] - width * right1[1];
10454 vert[ 5] = org1[2] - width * right1[2];
10455 vert[ 6] = org2[0] - width * right2[0];
10456 vert[ 7] = org2[1] - width * right2[1];
10457 vert[ 8] = org2[2] - width * right2[2];
10458 vert[ 9] = org2[0] + width * right2[0];
10459 vert[10] = org2[1] + width * right2[1];
10460 vert[11] = org2[2] + width * right2[2];
10463 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)
10465 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
10466 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
10467 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
10468 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
10469 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
10470 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
10471 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
10472 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
10473 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
10474 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
10475 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
10476 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
10479 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
10484 VectorSet(v, x, y, z);
10485 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
10486 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
10488 if (i == mesh->numvertices)
10490 if (mesh->numvertices < mesh->maxvertices)
10492 VectorCopy(v, vertex3f);
10493 mesh->numvertices++;
10495 return mesh->numvertices;
10501 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
10504 int *e, element[3];
10505 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10506 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10507 e = mesh->element3i + mesh->numtriangles * 3;
10508 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
10510 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
10511 if (mesh->numtriangles < mesh->maxtriangles)
10516 mesh->numtriangles++;
10518 element[1] = element[2];
10522 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
10525 int *e, element[3];
10526 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10527 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10528 e = mesh->element3i + mesh->numtriangles * 3;
10529 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10531 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10532 if (mesh->numtriangles < mesh->maxtriangles)
10537 mesh->numtriangles++;
10539 element[1] = element[2];
10543 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10544 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10546 int planenum, planenum2;
10549 mplane_t *plane, *plane2;
10551 double temppoints[2][256*3];
10552 // figure out how large a bounding box we need to properly compute this brush
10554 for (w = 0;w < numplanes;w++)
10555 maxdist = max(maxdist, fabs(planes[w].dist));
10556 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10557 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10558 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10562 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10563 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10565 if (planenum2 == planenum)
10567 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);
10570 if (tempnumpoints < 3)
10572 // generate elements forming a triangle fan for this polygon
10573 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10577 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)
10579 texturelayer_t *layer;
10580 layer = t->currentlayers + t->currentnumlayers++;
10581 layer->type = type;
10582 layer->depthmask = depthmask;
10583 layer->blendfunc1 = blendfunc1;
10584 layer->blendfunc2 = blendfunc2;
10585 layer->texture = texture;
10586 layer->texmatrix = *matrix;
10587 layer->color[0] = r;
10588 layer->color[1] = g;
10589 layer->color[2] = b;
10590 layer->color[3] = a;
10593 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10595 if(parms[0] == 0 && parms[1] == 0)
10597 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10598 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10603 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10606 index = parms[2] + r_refdef.scene.time * parms[3];
10607 index -= floor(index);
10608 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10611 case Q3WAVEFUNC_NONE:
10612 case Q3WAVEFUNC_NOISE:
10613 case Q3WAVEFUNC_COUNT:
10616 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10617 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10618 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10619 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10620 case Q3WAVEFUNC_TRIANGLE:
10622 f = index - floor(index);
10625 else if (index < 2)
10627 else if (index < 3)
10633 f = parms[0] + parms[1] * f;
10634 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10635 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10639 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10644 matrix4x4_t matrix, temp;
10645 switch(tcmod->tcmod)
10647 case Q3TCMOD_COUNT:
10649 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10650 matrix = r_waterscrollmatrix;
10652 matrix = identitymatrix;
10654 case Q3TCMOD_ENTITYTRANSLATE:
10655 // this is used in Q3 to allow the gamecode to control texcoord
10656 // scrolling on the entity, which is not supported in darkplaces yet.
10657 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10659 case Q3TCMOD_ROTATE:
10660 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10661 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10662 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10664 case Q3TCMOD_SCALE:
10665 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10667 case Q3TCMOD_SCROLL:
10668 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10670 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10671 w = (int) tcmod->parms[0];
10672 h = (int) tcmod->parms[1];
10673 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10675 idx = (int) floor(f * w * h);
10676 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10678 case Q3TCMOD_STRETCH:
10679 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10680 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10682 case Q3TCMOD_TRANSFORM:
10683 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
10684 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
10685 VectorSet(tcmat + 6, 0 , 0 , 1);
10686 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
10687 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10689 case Q3TCMOD_TURBULENT:
10690 // this is handled in the RSurf_PrepareVertices function
10691 matrix = identitymatrix;
10695 Matrix4x4_Concat(texmatrix, &matrix, &temp);
10698 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10700 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10701 char name[MAX_QPATH];
10702 skinframe_t *skinframe;
10703 unsigned char pixels[296*194];
10704 strlcpy(cache->name, skinname, sizeof(cache->name));
10705 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10706 if (developer_loading.integer)
10707 Con_Printf("loading %s\n", name);
10708 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10709 if (!skinframe || !skinframe->base)
10712 fs_offset_t filesize;
10714 f = FS_LoadFile(name, tempmempool, true, &filesize);
10717 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10718 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10722 cache->skinframe = skinframe;
10725 texture_t *R_GetCurrentTexture(texture_t *t)
10728 const entity_render_t *ent = rsurface.entity;
10729 dp_model_t *model = ent->model;
10730 q3shaderinfo_layer_tcmod_t *tcmod;
10732 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10733 return t->currentframe;
10734 t->update_lastrenderframe = r_textureframe;
10735 t->update_lastrenderentity = (void *)ent;
10737 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10738 t->camera_entity = ent->entitynumber;
10740 t->camera_entity = 0;
10742 // switch to an alternate material if this is a q1bsp animated material
10744 texture_t *texture = t;
10745 int s = rsurface.ent_skinnum;
10746 if ((unsigned int)s >= (unsigned int)model->numskins)
10748 if (model->skinscenes)
10750 if (model->skinscenes[s].framecount > 1)
10751 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10753 s = model->skinscenes[s].firstframe;
10756 t = t + s * model->num_surfaces;
10759 // use an alternate animation if the entity's frame is not 0,
10760 // and only if the texture has an alternate animation
10761 if (rsurface.ent_alttextures && t->anim_total[1])
10762 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10764 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10766 texture->currentframe = t;
10769 // update currentskinframe to be a qw skin or animation frame
10770 if (rsurface.ent_qwskin >= 0)
10772 i = rsurface.ent_qwskin;
10773 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10775 r_qwskincache_size = cl.maxclients;
10777 Mem_Free(r_qwskincache);
10778 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10780 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10781 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10782 t->currentskinframe = r_qwskincache[i].skinframe;
10783 if (t->currentskinframe == NULL)
10784 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10786 else if (t->numskinframes >= 2)
10787 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10788 if (t->backgroundnumskinframes >= 2)
10789 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10791 t->currentmaterialflags = t->basematerialflags;
10792 t->currentalpha = rsurface.colormod[3];
10793 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10794 t->currentalpha *= r_wateralpha.value;
10795 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10796 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10797 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10798 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10799 if (!(rsurface.ent_flags & RENDER_LIGHT))
10800 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10801 else if (FAKELIGHT_ENABLED)
10803 // no modellight if using fakelight for the map
10805 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10807 // pick a model lighting mode
10808 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10809 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10811 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10813 if (rsurface.ent_flags & RENDER_ADDITIVE)
10814 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10815 else if (t->currentalpha < 1)
10816 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10817 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10818 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10819 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10820 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10821 if (t->backgroundnumskinframes)
10822 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10823 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10825 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10826 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10829 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10830 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10831 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10833 // there is no tcmod
10834 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10836 t->currenttexmatrix = r_waterscrollmatrix;
10837 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10839 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10841 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10842 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10845 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10846 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10847 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10848 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10850 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10851 if (t->currentskinframe->qpixels)
10852 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10853 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10854 if (!t->basetexture)
10855 t->basetexture = r_texture_notexture;
10856 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10857 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10858 t->nmaptexture = t->currentskinframe->nmap;
10859 if (!t->nmaptexture)
10860 t->nmaptexture = r_texture_blanknormalmap;
10861 t->glosstexture = r_texture_black;
10862 t->glowtexture = t->currentskinframe->glow;
10863 t->fogtexture = t->currentskinframe->fog;
10864 t->reflectmasktexture = t->currentskinframe->reflect;
10865 if (t->backgroundnumskinframes)
10867 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10868 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10869 t->backgroundglosstexture = r_texture_black;
10870 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10871 if (!t->backgroundnmaptexture)
10872 t->backgroundnmaptexture = r_texture_blanknormalmap;
10876 t->backgroundbasetexture = r_texture_white;
10877 t->backgroundnmaptexture = r_texture_blanknormalmap;
10878 t->backgroundglosstexture = r_texture_black;
10879 t->backgroundglowtexture = NULL;
10881 t->specularpower = r_shadow_glossexponent.value;
10882 // TODO: store reference values for these in the texture?
10883 t->specularscale = 0;
10884 if (r_shadow_gloss.integer > 0)
10886 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10888 if (r_shadow_glossintensity.value > 0)
10890 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10891 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10892 t->specularscale = r_shadow_glossintensity.value;
10895 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10897 t->glosstexture = r_texture_white;
10898 t->backgroundglosstexture = r_texture_white;
10899 t->specularscale = r_shadow_gloss2intensity.value;
10900 t->specularpower = r_shadow_gloss2exponent.value;
10903 t->specularscale *= t->specularscalemod;
10904 t->specularpower *= t->specularpowermod;
10906 // lightmaps mode looks bad with dlights using actual texturing, so turn
10907 // off the colormap and glossmap, but leave the normalmap on as it still
10908 // accurately represents the shading involved
10909 if (gl_lightmaps.integer)
10911 t->basetexture = r_texture_grey128;
10912 t->pantstexture = r_texture_black;
10913 t->shirttexture = r_texture_black;
10914 t->nmaptexture = r_texture_blanknormalmap;
10915 t->glosstexture = r_texture_black;
10916 t->glowtexture = NULL;
10917 t->fogtexture = NULL;
10918 t->reflectmasktexture = NULL;
10919 t->backgroundbasetexture = NULL;
10920 t->backgroundnmaptexture = r_texture_blanknormalmap;
10921 t->backgroundglosstexture = r_texture_black;
10922 t->backgroundglowtexture = NULL;
10923 t->specularscale = 0;
10924 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10927 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10928 VectorClear(t->dlightcolor);
10929 t->currentnumlayers = 0;
10930 if (t->currentmaterialflags & MATERIALFLAG_WALL)
10932 int blendfunc1, blendfunc2;
10933 qboolean depthmask;
10934 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10936 blendfunc1 = GL_SRC_ALPHA;
10937 blendfunc2 = GL_ONE;
10939 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10941 blendfunc1 = GL_SRC_ALPHA;
10942 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10944 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10946 blendfunc1 = t->customblendfunc[0];
10947 blendfunc2 = t->customblendfunc[1];
10951 blendfunc1 = GL_ONE;
10952 blendfunc2 = GL_ZERO;
10954 // don't colormod evilblend textures
10955 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10956 VectorSet(t->lightmapcolor, 1, 1, 1);
10957 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10958 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10960 // fullbright is not affected by r_refdef.lightmapintensity
10961 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]);
10962 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10963 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]);
10964 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10965 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]);
10969 vec3_t ambientcolor;
10971 // set the color tint used for lights affecting this surface
10972 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10974 // q3bsp has no lightmap updates, so the lightstylevalue that
10975 // would normally be baked into the lightmap must be
10976 // applied to the color
10977 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10978 if (model->type == mod_brushq3)
10979 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10980 colorscale *= r_refdef.lightmapintensity;
10981 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10982 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10983 // basic lit geometry
10984 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]);
10985 // add pants/shirt if needed
10986 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10987 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]);
10988 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10989 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]);
10990 // now add ambient passes if needed
10991 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10993 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]);
10994 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10995 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]);
10996 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10997 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]);
11000 if (t->glowtexture != NULL && !gl_lightmaps.integer)
11001 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]);
11002 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
11004 // if this is opaque use alpha blend which will darken the earlier
11007 // if this is an alpha blended material, all the earlier passes
11008 // were darkened by fog already, so we only need to add the fog
11009 // color ontop through the fog mask texture
11011 // if this is an additive blended material, all the earlier passes
11012 // were darkened by fog already, and we should not add fog color
11013 // (because the background was not darkened, there is no fog color
11014 // that was lost behind it).
11015 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]);
11019 return t->currentframe;
11022 rsurfacestate_t rsurface;
11024 void RSurf_ActiveWorldEntity(void)
11026 dp_model_t *model = r_refdef.scene.worldmodel;
11027 //if (rsurface.entity == r_refdef.scene.worldentity)
11029 rsurface.entity = r_refdef.scene.worldentity;
11030 rsurface.skeleton = NULL;
11031 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
11032 rsurface.ent_skinnum = 0;
11033 rsurface.ent_qwskin = -1;
11034 rsurface.ent_shadertime = 0;
11035 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
11036 rsurface.matrix = identitymatrix;
11037 rsurface.inversematrix = identitymatrix;
11038 rsurface.matrixscale = 1;
11039 rsurface.inversematrixscale = 1;
11040 R_EntityMatrix(&identitymatrix);
11041 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
11042 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
11043 rsurface.fograngerecip = r_refdef.fograngerecip;
11044 rsurface.fogheightfade = r_refdef.fogheightfade;
11045 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
11046 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11047 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11048 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11049 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11050 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11051 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11052 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
11053 rsurface.colormod[3] = 1;
11054 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);
11055 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11056 rsurface.frameblend[0].lerp = 1;
11057 rsurface.ent_alttextures = false;
11058 rsurface.basepolygonfactor = r_refdef.polygonfactor;
11059 rsurface.basepolygonoffset = r_refdef.polygonoffset;
11060 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
11061 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11062 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
11063 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
11064 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11065 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
11066 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
11067 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11068 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
11069 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
11070 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11071 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
11072 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
11073 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11074 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11075 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
11076 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11077 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11078 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
11079 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11080 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11081 rsurface.modelelement3i = model->surfmesh.data_element3i;
11082 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11083 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11084 rsurface.modelelement3s = model->surfmesh.data_element3s;
11085 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11086 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11087 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11088 rsurface.modelnumvertices = model->surfmesh.num_vertices;
11089 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11090 rsurface.modelsurfaces = model->data_surfaces;
11091 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
11092 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
11093 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
11094 rsurface.modelgeneratedvertex = false;
11095 rsurface.batchgeneratedvertex = false;
11096 rsurface.batchfirstvertex = 0;
11097 rsurface.batchnumvertices = 0;
11098 rsurface.batchfirsttriangle = 0;
11099 rsurface.batchnumtriangles = 0;
11100 rsurface.batchvertex3f = NULL;
11101 rsurface.batchvertex3f_vertexbuffer = NULL;
11102 rsurface.batchvertex3f_bufferoffset = 0;
11103 rsurface.batchsvector3f = NULL;
11104 rsurface.batchsvector3f_vertexbuffer = NULL;
11105 rsurface.batchsvector3f_bufferoffset = 0;
11106 rsurface.batchtvector3f = NULL;
11107 rsurface.batchtvector3f_vertexbuffer = NULL;
11108 rsurface.batchtvector3f_bufferoffset = 0;
11109 rsurface.batchnormal3f = NULL;
11110 rsurface.batchnormal3f_vertexbuffer = NULL;
11111 rsurface.batchnormal3f_bufferoffset = 0;
11112 rsurface.batchlightmapcolor4f = NULL;
11113 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11114 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11115 rsurface.batchtexcoordtexture2f = NULL;
11116 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11117 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11118 rsurface.batchtexcoordlightmap2f = NULL;
11119 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11120 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11121 rsurface.batchvertexmesh = NULL;
11122 rsurface.batchvertexmeshbuffer = NULL;
11123 rsurface.batchvertex3fbuffer = NULL;
11124 rsurface.batchelement3i = NULL;
11125 rsurface.batchelement3i_indexbuffer = NULL;
11126 rsurface.batchelement3i_bufferoffset = 0;
11127 rsurface.batchelement3s = NULL;
11128 rsurface.batchelement3s_indexbuffer = NULL;
11129 rsurface.batchelement3s_bufferoffset = 0;
11130 rsurface.passcolor4f = NULL;
11131 rsurface.passcolor4f_vertexbuffer = NULL;
11132 rsurface.passcolor4f_bufferoffset = 0;
11135 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
11137 dp_model_t *model = ent->model;
11138 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
11140 rsurface.entity = (entity_render_t *)ent;
11141 rsurface.skeleton = ent->skeleton;
11142 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
11143 rsurface.ent_skinnum = ent->skinnum;
11144 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;
11145 rsurface.ent_shadertime = ent->shadertime;
11146 rsurface.ent_flags = ent->flags;
11147 rsurface.matrix = ent->matrix;
11148 rsurface.inversematrix = ent->inversematrix;
11149 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11150 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11151 R_EntityMatrix(&rsurface.matrix);
11152 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11153 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11154 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11155 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11156 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11157 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11158 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
11159 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
11160 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
11161 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
11162 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
11163 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
11164 rsurface.colormod[3] = ent->alpha;
11165 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
11166 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
11167 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
11168 rsurface.basepolygonfactor = r_refdef.polygonfactor;
11169 rsurface.basepolygonoffset = r_refdef.polygonoffset;
11170 if (ent->model->brush.submodel && !prepass)
11172 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
11173 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
11175 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
11177 if (ent->animcache_vertex3f)
11179 rsurface.modelvertex3f = ent->animcache_vertex3f;
11180 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
11181 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
11182 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
11183 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
11184 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
11185 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
11187 else if (wanttangents)
11189 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11190 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11191 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11192 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11193 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
11194 rsurface.modelvertexmesh = NULL;
11195 rsurface.modelvertexmeshbuffer = NULL;
11196 rsurface.modelvertex3fbuffer = NULL;
11198 else if (wantnormals)
11200 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11201 rsurface.modelsvector3f = NULL;
11202 rsurface.modeltvector3f = NULL;
11203 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11204 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
11205 rsurface.modelvertexmesh = NULL;
11206 rsurface.modelvertexmeshbuffer = NULL;
11207 rsurface.modelvertex3fbuffer = NULL;
11211 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11212 rsurface.modelsvector3f = NULL;
11213 rsurface.modeltvector3f = NULL;
11214 rsurface.modelnormal3f = NULL;
11215 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
11216 rsurface.modelvertexmesh = NULL;
11217 rsurface.modelvertexmeshbuffer = NULL;
11218 rsurface.modelvertex3fbuffer = NULL;
11220 rsurface.modelvertex3f_vertexbuffer = 0;
11221 rsurface.modelvertex3f_bufferoffset = 0;
11222 rsurface.modelsvector3f_vertexbuffer = 0;
11223 rsurface.modelsvector3f_bufferoffset = 0;
11224 rsurface.modeltvector3f_vertexbuffer = 0;
11225 rsurface.modeltvector3f_bufferoffset = 0;
11226 rsurface.modelnormal3f_vertexbuffer = 0;
11227 rsurface.modelnormal3f_bufferoffset = 0;
11228 rsurface.modelgeneratedvertex = true;
11232 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
11233 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11234 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
11235 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
11236 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11237 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
11238 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
11239 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11240 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
11241 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
11242 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11243 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
11244 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
11245 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
11246 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
11247 rsurface.modelgeneratedvertex = false;
11249 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
11250 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11251 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11252 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
11253 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11254 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11255 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
11256 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11257 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11258 rsurface.modelelement3i = model->surfmesh.data_element3i;
11259 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11260 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11261 rsurface.modelelement3s = model->surfmesh.data_element3s;
11262 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11263 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11264 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11265 rsurface.modelnumvertices = model->surfmesh.num_vertices;
11266 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11267 rsurface.modelsurfaces = model->data_surfaces;
11268 rsurface.batchgeneratedvertex = false;
11269 rsurface.batchfirstvertex = 0;
11270 rsurface.batchnumvertices = 0;
11271 rsurface.batchfirsttriangle = 0;
11272 rsurface.batchnumtriangles = 0;
11273 rsurface.batchvertex3f = NULL;
11274 rsurface.batchvertex3f_vertexbuffer = NULL;
11275 rsurface.batchvertex3f_bufferoffset = 0;
11276 rsurface.batchsvector3f = NULL;
11277 rsurface.batchsvector3f_vertexbuffer = NULL;
11278 rsurface.batchsvector3f_bufferoffset = 0;
11279 rsurface.batchtvector3f = NULL;
11280 rsurface.batchtvector3f_vertexbuffer = NULL;
11281 rsurface.batchtvector3f_bufferoffset = 0;
11282 rsurface.batchnormal3f = NULL;
11283 rsurface.batchnormal3f_vertexbuffer = NULL;
11284 rsurface.batchnormal3f_bufferoffset = 0;
11285 rsurface.batchlightmapcolor4f = NULL;
11286 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11287 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11288 rsurface.batchtexcoordtexture2f = NULL;
11289 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11290 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11291 rsurface.batchtexcoordlightmap2f = NULL;
11292 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11293 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11294 rsurface.batchvertexmesh = NULL;
11295 rsurface.batchvertexmeshbuffer = NULL;
11296 rsurface.batchvertex3fbuffer = NULL;
11297 rsurface.batchelement3i = NULL;
11298 rsurface.batchelement3i_indexbuffer = NULL;
11299 rsurface.batchelement3i_bufferoffset = 0;
11300 rsurface.batchelement3s = NULL;
11301 rsurface.batchelement3s_indexbuffer = NULL;
11302 rsurface.batchelement3s_bufferoffset = 0;
11303 rsurface.passcolor4f = NULL;
11304 rsurface.passcolor4f_vertexbuffer = NULL;
11305 rsurface.passcolor4f_bufferoffset = 0;
11308 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)
11310 rsurface.entity = r_refdef.scene.worldentity;
11311 rsurface.skeleton = NULL;
11312 rsurface.ent_skinnum = 0;
11313 rsurface.ent_qwskin = -1;
11314 rsurface.ent_shadertime = shadertime;
11315 rsurface.ent_flags = entflags;
11316 rsurface.modelnumvertices = numvertices;
11317 rsurface.modelnumtriangles = numtriangles;
11318 rsurface.matrix = *matrix;
11319 rsurface.inversematrix = *inversematrix;
11320 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11321 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11322 R_EntityMatrix(&rsurface.matrix);
11323 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11324 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11325 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11326 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11327 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11328 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11329 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11330 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11331 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11332 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11333 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11334 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
11335 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);
11336 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11337 rsurface.frameblend[0].lerp = 1;
11338 rsurface.ent_alttextures = false;
11339 rsurface.basepolygonfactor = r_refdef.polygonfactor;
11340 rsurface.basepolygonoffset = r_refdef.polygonoffset;
11343 rsurface.modelvertex3f = (float *)vertex3f;
11344 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11345 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11346 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11348 else if (wantnormals)
11350 rsurface.modelvertex3f = (float *)vertex3f;
11351 rsurface.modelsvector3f = NULL;
11352 rsurface.modeltvector3f = NULL;
11353 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11357 rsurface.modelvertex3f = (float *)vertex3f;
11358 rsurface.modelsvector3f = NULL;
11359 rsurface.modeltvector3f = NULL;
11360 rsurface.modelnormal3f = NULL;
11362 rsurface.modelvertexmesh = NULL;
11363 rsurface.modelvertexmeshbuffer = NULL;
11364 rsurface.modelvertex3fbuffer = NULL;
11365 rsurface.modelvertex3f_vertexbuffer = 0;
11366 rsurface.modelvertex3f_bufferoffset = 0;
11367 rsurface.modelsvector3f_vertexbuffer = 0;
11368 rsurface.modelsvector3f_bufferoffset = 0;
11369 rsurface.modeltvector3f_vertexbuffer = 0;
11370 rsurface.modeltvector3f_bufferoffset = 0;
11371 rsurface.modelnormal3f_vertexbuffer = 0;
11372 rsurface.modelnormal3f_bufferoffset = 0;
11373 rsurface.modelgeneratedvertex = true;
11374 rsurface.modellightmapcolor4f = (float *)color4f;
11375 rsurface.modellightmapcolor4f_vertexbuffer = 0;
11376 rsurface.modellightmapcolor4f_bufferoffset = 0;
11377 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
11378 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
11379 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
11380 rsurface.modeltexcoordlightmap2f = NULL;
11381 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
11382 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
11383 rsurface.modelelement3i = (int *)element3i;
11384 rsurface.modelelement3i_indexbuffer = NULL;
11385 rsurface.modelelement3i_bufferoffset = 0;
11386 rsurface.modelelement3s = (unsigned short *)element3s;
11387 rsurface.modelelement3s_indexbuffer = NULL;
11388 rsurface.modelelement3s_bufferoffset = 0;
11389 rsurface.modellightmapoffsets = NULL;
11390 rsurface.modelsurfaces = NULL;
11391 rsurface.batchgeneratedvertex = false;
11392 rsurface.batchfirstvertex = 0;
11393 rsurface.batchnumvertices = 0;
11394 rsurface.batchfirsttriangle = 0;
11395 rsurface.batchnumtriangles = 0;
11396 rsurface.batchvertex3f = NULL;
11397 rsurface.batchvertex3f_vertexbuffer = NULL;
11398 rsurface.batchvertex3f_bufferoffset = 0;
11399 rsurface.batchsvector3f = NULL;
11400 rsurface.batchsvector3f_vertexbuffer = NULL;
11401 rsurface.batchsvector3f_bufferoffset = 0;
11402 rsurface.batchtvector3f = NULL;
11403 rsurface.batchtvector3f_vertexbuffer = NULL;
11404 rsurface.batchtvector3f_bufferoffset = 0;
11405 rsurface.batchnormal3f = NULL;
11406 rsurface.batchnormal3f_vertexbuffer = NULL;
11407 rsurface.batchnormal3f_bufferoffset = 0;
11408 rsurface.batchlightmapcolor4f = NULL;
11409 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11410 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11411 rsurface.batchtexcoordtexture2f = NULL;
11412 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11413 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11414 rsurface.batchtexcoordlightmap2f = NULL;
11415 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11416 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11417 rsurface.batchvertexmesh = NULL;
11418 rsurface.batchvertexmeshbuffer = NULL;
11419 rsurface.batchvertex3fbuffer = NULL;
11420 rsurface.batchelement3i = NULL;
11421 rsurface.batchelement3i_indexbuffer = NULL;
11422 rsurface.batchelement3i_bufferoffset = 0;
11423 rsurface.batchelement3s = NULL;
11424 rsurface.batchelement3s_indexbuffer = NULL;
11425 rsurface.batchelement3s_bufferoffset = 0;
11426 rsurface.passcolor4f = NULL;
11427 rsurface.passcolor4f_vertexbuffer = NULL;
11428 rsurface.passcolor4f_bufferoffset = 0;
11430 if (rsurface.modelnumvertices && rsurface.modelelement3i)
11432 if ((wantnormals || wanttangents) && !normal3f)
11434 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11435 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
11437 if (wanttangents && !svector3f)
11439 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11440 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11441 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
11446 float RSurf_FogPoint(const float *v)
11448 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11449 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11450 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11451 float FogHeightFade = r_refdef.fogheightfade;
11453 unsigned int fogmasktableindex;
11454 if (r_refdef.fogplaneviewabove)
11455 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11457 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11458 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11459 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11462 float RSurf_FogVertex(const float *v)
11464 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11465 float FogPlaneViewDist = rsurface.fogplaneviewdist;
11466 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11467 float FogHeightFade = rsurface.fogheightfade;
11469 unsigned int fogmasktableindex;
11470 if (r_refdef.fogplaneviewabove)
11471 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11473 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11474 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11475 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11478 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11481 for (i = 0;i < numelements;i++)
11482 outelement3i[i] = inelement3i[i] + adjust;
11485 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11486 extern cvar_t gl_vbo;
11487 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11495 int surfacefirsttriangle;
11496 int surfacenumtriangles;
11497 int surfacefirstvertex;
11498 int surfaceendvertex;
11499 int surfacenumvertices;
11500 int batchnumvertices;
11501 int batchnumtriangles;
11505 qboolean dynamicvertex;
11509 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11510 float waveparms[4];
11511 q3shaderinfo_deform_t *deform;
11512 const msurface_t *surface, *firstsurface;
11513 r_vertexmesh_t *vertexmesh;
11514 if (!texturenumsurfaces)
11516 // find vertex range of this surface batch
11518 firstsurface = texturesurfacelist[0];
11519 firsttriangle = firstsurface->num_firsttriangle;
11520 batchnumvertices = 0;
11521 batchnumtriangles = 0;
11522 firstvertex = endvertex = firstsurface->num_firstvertex;
11523 for (i = 0;i < texturenumsurfaces;i++)
11525 surface = texturesurfacelist[i];
11526 if (surface != firstsurface + i)
11528 surfacefirstvertex = surface->num_firstvertex;
11529 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11530 surfacenumvertices = surface->num_vertices;
11531 surfacenumtriangles = surface->num_triangles;
11532 if (firstvertex > surfacefirstvertex)
11533 firstvertex = surfacefirstvertex;
11534 if (endvertex < surfaceendvertex)
11535 endvertex = surfaceendvertex;
11536 batchnumvertices += surfacenumvertices;
11537 batchnumtriangles += surfacenumtriangles;
11540 // we now know the vertex range used, and if there are any gaps in it
11541 rsurface.batchfirstvertex = firstvertex;
11542 rsurface.batchnumvertices = endvertex - firstvertex;
11543 rsurface.batchfirsttriangle = firsttriangle;
11544 rsurface.batchnumtriangles = batchnumtriangles;
11546 // this variable holds flags for which properties have been updated that
11547 // may require regenerating vertexmesh array...
11550 // check if any dynamic vertex processing must occur
11551 dynamicvertex = false;
11553 // if there is a chance of animated vertex colors, it's a dynamic batch
11554 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11556 dynamicvertex = true;
11557 batchneed |= BATCHNEED_NOGAPS;
11558 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
11561 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11563 switch (deform->deform)
11566 case Q3DEFORM_PROJECTIONSHADOW:
11567 case Q3DEFORM_TEXT0:
11568 case Q3DEFORM_TEXT1:
11569 case Q3DEFORM_TEXT2:
11570 case Q3DEFORM_TEXT3:
11571 case Q3DEFORM_TEXT4:
11572 case Q3DEFORM_TEXT5:
11573 case Q3DEFORM_TEXT6:
11574 case Q3DEFORM_TEXT7:
11575 case Q3DEFORM_NONE:
11577 case Q3DEFORM_AUTOSPRITE:
11578 dynamicvertex = true;
11579 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11580 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11582 case Q3DEFORM_AUTOSPRITE2:
11583 dynamicvertex = true;
11584 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11585 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11587 case Q3DEFORM_NORMAL:
11588 dynamicvertex = true;
11589 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11590 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11592 case Q3DEFORM_WAVE:
11593 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11594 break; // if wavefunc is a nop, ignore this transform
11595 dynamicvertex = true;
11596 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11597 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11599 case Q3DEFORM_BULGE:
11600 dynamicvertex = true;
11601 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11602 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11604 case Q3DEFORM_MOVE:
11605 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11606 break; // if wavefunc is a nop, ignore this transform
11607 dynamicvertex = true;
11608 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11609 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
11613 switch(rsurface.texture->tcgen.tcgen)
11616 case Q3TCGEN_TEXTURE:
11618 case Q3TCGEN_LIGHTMAP:
11619 dynamicvertex = true;
11620 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11621 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11623 case Q3TCGEN_VECTOR:
11624 dynamicvertex = true;
11625 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11626 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11628 case Q3TCGEN_ENVIRONMENT:
11629 dynamicvertex = true;
11630 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11631 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11634 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11636 dynamicvertex = true;
11637 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11638 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11641 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11643 dynamicvertex = true;
11644 batchneed |= BATCHNEED_NOGAPS;
11645 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11648 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11650 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11651 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
11652 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
11653 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
11654 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11655 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11656 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11659 // when the model data has no vertex buffer (dynamic mesh), we need to
11661 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
11662 batchneed |= BATCHNEED_NOGAPS;
11664 // if needsupdate, we have to do a dynamic vertex batch for sure
11665 if (needsupdate & batchneed)
11666 dynamicvertex = true;
11668 // see if we need to build vertexmesh from arrays
11669 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11670 dynamicvertex = true;
11672 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11673 // also some drivers strongly dislike firstvertex
11674 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11675 dynamicvertex = true;
11677 rsurface.batchvertex3f = rsurface.modelvertex3f;
11678 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11679 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11680 rsurface.batchsvector3f = rsurface.modelsvector3f;
11681 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11682 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11683 rsurface.batchtvector3f = rsurface.modeltvector3f;
11684 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11685 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11686 rsurface.batchnormal3f = rsurface.modelnormal3f;
11687 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11688 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11689 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11690 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
11691 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11692 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11693 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
11694 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
11695 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11696 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11697 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11698 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
11699 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11700 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11701 rsurface.batchelement3i = rsurface.modelelement3i;
11702 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11703 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11704 rsurface.batchelement3s = rsurface.modelelement3s;
11705 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11706 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11708 // if any dynamic vertex processing has to occur in software, we copy the
11709 // entire surface list together before processing to rebase the vertices
11710 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11712 // if any gaps exist and we do not have a static vertex buffer, we have to
11713 // copy the surface list together to avoid wasting upload bandwidth on the
11714 // vertices in the gaps.
11716 // if gaps exist and we have a static vertex buffer, we still have to
11717 // combine the index buffer ranges into one dynamic index buffer.
11719 // in all cases we end up with data that can be drawn in one call.
11721 if (!dynamicvertex)
11723 // static vertex data, just set pointers...
11724 rsurface.batchgeneratedvertex = false;
11725 // if there are gaps, we want to build a combined index buffer,
11726 // otherwise use the original static buffer with an appropriate offset
11729 // build a new triangle elements array for this batch
11730 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11731 rsurface.batchfirsttriangle = 0;
11733 for (i = 0;i < texturenumsurfaces;i++)
11735 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11736 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11737 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11738 numtriangles += surfacenumtriangles;
11740 rsurface.batchelement3i_indexbuffer = NULL;
11741 rsurface.batchelement3i_bufferoffset = 0;
11742 rsurface.batchelement3s = NULL;
11743 rsurface.batchelement3s_indexbuffer = NULL;
11744 rsurface.batchelement3s_bufferoffset = 0;
11745 if (endvertex <= 65536)
11747 // make a 16bit (unsigned short) index array if possible
11748 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11749 for (i = 0;i < numtriangles*3;i++)
11750 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11756 // something needs software processing, do it for real...
11757 // we only directly handle separate array data in this case and then
11758 // generate interleaved data if needed...
11759 rsurface.batchgeneratedvertex = true;
11761 // now copy the vertex data into a combined array and make an index array
11762 // (this is what Quake3 does all the time)
11763 //if (gaps || rsurface.batchfirstvertex)
11765 rsurface.batchvertex3fbuffer = NULL;
11766 rsurface.batchvertexmesh = NULL;
11767 rsurface.batchvertexmeshbuffer = NULL;
11768 rsurface.batchvertex3f = NULL;
11769 rsurface.batchvertex3f_vertexbuffer = NULL;
11770 rsurface.batchvertex3f_bufferoffset = 0;
11771 rsurface.batchsvector3f = NULL;
11772 rsurface.batchsvector3f_vertexbuffer = NULL;
11773 rsurface.batchsvector3f_bufferoffset = 0;
11774 rsurface.batchtvector3f = NULL;
11775 rsurface.batchtvector3f_vertexbuffer = NULL;
11776 rsurface.batchtvector3f_bufferoffset = 0;
11777 rsurface.batchnormal3f = NULL;
11778 rsurface.batchnormal3f_vertexbuffer = NULL;
11779 rsurface.batchnormal3f_bufferoffset = 0;
11780 rsurface.batchlightmapcolor4f = NULL;
11781 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11782 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11783 rsurface.batchtexcoordtexture2f = NULL;
11784 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11785 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11786 rsurface.batchtexcoordlightmap2f = NULL;
11787 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11788 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11789 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11790 rsurface.batchelement3i_indexbuffer = NULL;
11791 rsurface.batchelement3i_bufferoffset = 0;
11792 rsurface.batchelement3s = NULL;
11793 rsurface.batchelement3s_indexbuffer = NULL;
11794 rsurface.batchelement3s_bufferoffset = 0;
11795 // we'll only be setting up certain arrays as needed
11796 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11797 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
11798 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11799 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11800 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11801 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11802 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11804 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11805 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11807 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11808 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11809 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11810 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11811 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11812 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11815 for (i = 0;i < texturenumsurfaces;i++)
11817 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11818 surfacenumvertices = texturesurfacelist[i]->num_vertices;
11819 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11820 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11821 // copy only the data requested
11822 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11823 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11824 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11826 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11827 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11828 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11829 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11830 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11832 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11833 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11835 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11836 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11837 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11838 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11839 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11840 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11842 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11843 numvertices += surfacenumvertices;
11844 numtriangles += surfacenumtriangles;
11847 // generate a 16bit index array as well if possible
11848 // (in general, dynamic batches fit)
11849 if (numvertices <= 65536)
11851 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11852 for (i = 0;i < numtriangles*3;i++)
11853 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11856 // since we've copied everything, the batch now starts at 0
11857 rsurface.batchfirstvertex = 0;
11858 rsurface.batchnumvertices = batchnumvertices;
11859 rsurface.batchfirsttriangle = 0;
11860 rsurface.batchnumtriangles = batchnumtriangles;
11863 // q1bsp surfaces rendered in vertex color mode have to have colors
11864 // calculated based on lightstyles
11865 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11867 // generate color arrays for the surfaces in this list
11871 const int *offsets;
11872 const unsigned char *lm;
11873 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11874 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11875 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11877 for (i = 0;i < texturenumsurfaces;i++)
11879 surface = texturesurfacelist[i];
11880 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11881 surfacenumvertices = surface->num_vertices;
11882 if (surface->lightmapinfo->samples)
11884 for (j = 0;j < surfacenumvertices;j++)
11886 lm = surface->lightmapinfo->samples + offsets[j];
11887 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11888 VectorScale(lm, scale, c);
11889 if (surface->lightmapinfo->styles[1] != 255)
11891 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11893 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11894 VectorMA(c, scale, lm, c);
11895 if (surface->lightmapinfo->styles[2] != 255)
11898 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11899 VectorMA(c, scale, lm, c);
11900 if (surface->lightmapinfo->styles[3] != 255)
11903 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11904 VectorMA(c, scale, lm, c);
11911 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);
11917 for (j = 0;j < surfacenumvertices;j++)
11919 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11926 // if vertices are deformed (sprite flares and things in maps, possibly
11927 // water waves, bulges and other deformations), modify the copied vertices
11929 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11931 switch (deform->deform)
11934 case Q3DEFORM_PROJECTIONSHADOW:
11935 case Q3DEFORM_TEXT0:
11936 case Q3DEFORM_TEXT1:
11937 case Q3DEFORM_TEXT2:
11938 case Q3DEFORM_TEXT3:
11939 case Q3DEFORM_TEXT4:
11940 case Q3DEFORM_TEXT5:
11941 case Q3DEFORM_TEXT6:
11942 case Q3DEFORM_TEXT7:
11943 case Q3DEFORM_NONE:
11945 case Q3DEFORM_AUTOSPRITE:
11946 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11947 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11948 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11949 VectorNormalize(newforward);
11950 VectorNormalize(newright);
11951 VectorNormalize(newup);
11952 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11953 // rsurface.batchvertex3f_vertexbuffer = NULL;
11954 // rsurface.batchvertex3f_bufferoffset = 0;
11955 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
11956 // rsurface.batchsvector3f_vertexbuffer = NULL;
11957 // rsurface.batchsvector3f_bufferoffset = 0;
11958 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
11959 // rsurface.batchtvector3f_vertexbuffer = NULL;
11960 // rsurface.batchtvector3f_bufferoffset = 0;
11961 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11962 // rsurface.batchnormal3f_vertexbuffer = NULL;
11963 // rsurface.batchnormal3f_bufferoffset = 0;
11964 // a single autosprite surface can contain multiple sprites...
11965 for (j = 0;j < batchnumvertices - 3;j += 4)
11967 VectorClear(center);
11968 for (i = 0;i < 4;i++)
11969 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11970 VectorScale(center, 0.25f, center);
11971 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11972 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11973 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11974 for (i = 0;i < 4;i++)
11976 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11977 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
11980 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11981 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11982 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);
11984 case Q3DEFORM_AUTOSPRITE2:
11985 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11986 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11987 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11988 VectorNormalize(newforward);
11989 VectorNormalize(newright);
11990 VectorNormalize(newup);
11991 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11992 // rsurface.batchvertex3f_vertexbuffer = NULL;
11993 // rsurface.batchvertex3f_bufferoffset = 0;
11995 const float *v1, *v2;
12005 memset(shortest, 0, sizeof(shortest));
12006 // a single autosprite surface can contain multiple sprites...
12007 for (j = 0;j < batchnumvertices - 3;j += 4)
12009 VectorClear(center);
12010 for (i = 0;i < 4;i++)
12011 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
12012 VectorScale(center, 0.25f, center);
12013 // find the two shortest edges, then use them to define the
12014 // axis vectors for rotating around the central axis
12015 for (i = 0;i < 6;i++)
12017 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
12018 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
12019 l = VectorDistance2(v1, v2);
12020 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
12021 if (v1[2] != v2[2])
12022 l += (1.0f / 1024.0f);
12023 if (shortest[0].length2 > l || i == 0)
12025 shortest[1] = shortest[0];
12026 shortest[0].length2 = l;
12027 shortest[0].v1 = v1;
12028 shortest[0].v2 = v2;
12030 else if (shortest[1].length2 > l || i == 1)
12032 shortest[1].length2 = l;
12033 shortest[1].v1 = v1;
12034 shortest[1].v2 = v2;
12037 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
12038 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
12039 // this calculates the right vector from the shortest edge
12040 // and the up vector from the edge midpoints
12041 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
12042 VectorNormalize(right);
12043 VectorSubtract(end, start, up);
12044 VectorNormalize(up);
12045 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
12046 VectorSubtract(rsurface.localvieworigin, center, forward);
12047 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
12048 VectorNegate(forward, forward);
12049 VectorReflect(forward, 0, up, forward);
12050 VectorNormalize(forward);
12051 CrossProduct(up, forward, newright);
12052 VectorNormalize(newright);
12053 // rotate the quad around the up axis vector, this is made
12054 // especially easy by the fact we know the quad is flat,
12055 // so we only have to subtract the center position and
12056 // measure distance along the right vector, and then
12057 // multiply that by the newright vector and add back the
12059 // we also need to subtract the old position to undo the
12060 // displacement from the center, which we do with a
12061 // DotProduct, the subtraction/addition of center is also
12062 // optimized into DotProducts here
12063 l = DotProduct(right, center);
12064 for (i = 0;i < 4;i++)
12066 v1 = rsurface.batchvertex3f + 3*(j+i);
12067 f = DotProduct(right, v1) - l;
12068 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
12072 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
12074 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12075 // rsurface.batchnormal3f_vertexbuffer = NULL;
12076 // rsurface.batchnormal3f_bufferoffset = 0;
12077 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12079 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12081 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12082 // rsurface.batchsvector3f_vertexbuffer = NULL;
12083 // rsurface.batchsvector3f_bufferoffset = 0;
12084 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12085 // rsurface.batchtvector3f_vertexbuffer = NULL;
12086 // rsurface.batchtvector3f_bufferoffset = 0;
12087 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);
12090 case Q3DEFORM_NORMAL:
12091 // deform the normals to make reflections wavey
12092 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
12093 rsurface.batchnormal3f_vertexbuffer = NULL;
12094 rsurface.batchnormal3f_bufferoffset = 0;
12095 for (j = 0;j < batchnumvertices;j++)
12098 float *normal = rsurface.batchnormal3f + 3*j;
12099 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
12100 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
12101 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]);
12102 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]);
12103 VectorNormalize(normal);
12105 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12107 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12108 // rsurface.batchsvector3f_vertexbuffer = NULL;
12109 // rsurface.batchsvector3f_bufferoffset = 0;
12110 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12111 // rsurface.batchtvector3f_vertexbuffer = NULL;
12112 // rsurface.batchtvector3f_bufferoffset = 0;
12113 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);
12116 case Q3DEFORM_WAVE:
12117 // deform vertex array to make wavey water and flags and such
12118 waveparms[0] = deform->waveparms[0];
12119 waveparms[1] = deform->waveparms[1];
12120 waveparms[2] = deform->waveparms[2];
12121 waveparms[3] = deform->waveparms[3];
12122 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
12123 break; // if wavefunc is a nop, don't make a dynamic vertex array
12124 // this is how a divisor of vertex influence on deformation
12125 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
12126 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
12127 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
12128 // rsurface.batchvertex3f_vertexbuffer = NULL;
12129 // rsurface.batchvertex3f_bufferoffset = 0;
12130 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
12131 // rsurface.batchnormal3f_vertexbuffer = NULL;
12132 // rsurface.batchnormal3f_bufferoffset = 0;
12133 for (j = 0;j < batchnumvertices;j++)
12135 // if the wavefunc depends on time, evaluate it per-vertex
12138 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
12139 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
12141 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
12143 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12144 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12145 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12147 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12148 // rsurface.batchsvector3f_vertexbuffer = NULL;
12149 // rsurface.batchsvector3f_bufferoffset = 0;
12150 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12151 // rsurface.batchtvector3f_vertexbuffer = NULL;
12152 // rsurface.batchtvector3f_bufferoffset = 0;
12153 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);
12156 case Q3DEFORM_BULGE:
12157 // deform vertex array to make the surface have moving bulges
12158 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
12159 // rsurface.batchvertex3f_vertexbuffer = NULL;
12160 // rsurface.batchvertex3f_bufferoffset = 0;
12161 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
12162 // rsurface.batchnormal3f_vertexbuffer = NULL;
12163 // rsurface.batchnormal3f_bufferoffset = 0;
12164 for (j = 0;j < batchnumvertices;j++)
12166 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
12167 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
12169 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12170 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12171 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12173 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12174 // rsurface.batchsvector3f_vertexbuffer = NULL;
12175 // rsurface.batchsvector3f_bufferoffset = 0;
12176 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12177 // rsurface.batchtvector3f_vertexbuffer = NULL;
12178 // rsurface.batchtvector3f_bufferoffset = 0;
12179 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);
12182 case Q3DEFORM_MOVE:
12183 // deform vertex array
12184 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
12185 break; // if wavefunc is a nop, don't make a dynamic vertex array
12186 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
12187 VectorScale(deform->parms, scale, waveparms);
12188 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
12189 // rsurface.batchvertex3f_vertexbuffer = NULL;
12190 // rsurface.batchvertex3f_bufferoffset = 0;
12191 for (j = 0;j < batchnumvertices;j++)
12192 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
12197 // generate texcoords based on the chosen texcoord source
12198 switch(rsurface.texture->tcgen.tcgen)
12201 case Q3TCGEN_TEXTURE:
12203 case Q3TCGEN_LIGHTMAP:
12204 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12205 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12206 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12207 if (rsurface.batchtexcoordlightmap2f)
12208 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
12210 case Q3TCGEN_VECTOR:
12211 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12212 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12213 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12214 for (j = 0;j < batchnumvertices;j++)
12216 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
12217 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
12220 case Q3TCGEN_ENVIRONMENT:
12221 // make environment reflections using a spheremap
12222 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12223 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12224 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12225 for (j = 0;j < batchnumvertices;j++)
12227 // identical to Q3A's method, but executed in worldspace so
12228 // carried models can be shiny too
12230 float viewer[3], d, reflected[3], worldreflected[3];
12232 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
12233 // VectorNormalize(viewer);
12235 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
12237 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
12238 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
12239 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
12240 // note: this is proportinal to viewer, so we can normalize later
12242 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
12243 VectorNormalize(worldreflected);
12245 // note: this sphere map only uses world x and z!
12246 // so positive and negative y will LOOK THE SAME.
12247 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
12248 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
12252 // the only tcmod that needs software vertex processing is turbulent, so
12253 // check for it here and apply the changes if needed
12254 // and we only support that as the first one
12255 // (handling a mixture of turbulent and other tcmods would be problematic
12256 // without punting it entirely to a software path)
12257 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
12259 amplitude = rsurface.texture->tcmods[0].parms[1];
12260 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
12261 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12262 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12263 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12264 for (j = 0;j < batchnumvertices;j++)
12266 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);
12267 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12271 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
12273 // convert the modified arrays to vertex structs
12274 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
12275 // rsurface.batchvertexmeshbuffer = NULL;
12276 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
12277 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12278 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
12279 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
12280 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12281 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
12282 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
12284 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12286 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
12287 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
12290 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
12291 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12292 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
12293 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
12294 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12295 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
12296 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
12297 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12298 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
12302 void RSurf_DrawBatch(void)
12304 // sometimes a zero triangle surface (usually a degenerate patch) makes it
12305 // through the pipeline, killing it earlier in the pipeline would have
12306 // per-surface overhead rather than per-batch overhead, so it's best to
12307 // reject it here, before it hits glDraw.
12308 if (rsurface.batchnumtriangles == 0)
12311 // batch debugging code
12312 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
12318 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
12319 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
12322 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
12324 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
12326 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
12327 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);
12334 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);
12337 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
12339 // pick the closest matching water plane
12340 int planeindex, vertexindex, bestplaneindex = -1;
12344 r_waterstate_waterplane_t *p;
12345 qboolean prepared = false;
12347 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
12349 if(p->camera_entity != rsurface.texture->camera_entity)
12354 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12356 if(rsurface.batchnumvertices == 0)
12359 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
12361 Matrix4x4_Transform(&rsurface.matrix, v, vert);
12362 d += fabs(PlaneDiff(vert, &p->plane));
12364 if (bestd > d || bestplaneindex < 0)
12367 bestplaneindex = planeindex;
12370 return bestplaneindex;
12371 // NOTE: this MAY return a totally unrelated water plane; we can ignore
12372 // this situation though, as it might be better to render single larger
12373 // batches with useless stuff (backface culled for example) than to
12374 // render multiple smaller batches
12377 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
12380 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12381 rsurface.passcolor4f_vertexbuffer = 0;
12382 rsurface.passcolor4f_bufferoffset = 0;
12383 for (i = 0;i < rsurface.batchnumvertices;i++)
12384 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
12387 static void RSurf_DrawBatch_GL11_ApplyFog(void)
12394 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12395 rsurface.passcolor4f_vertexbuffer = 0;
12396 rsurface.passcolor4f_bufferoffset = 0;
12397 if (rsurface.passcolor4f)
12399 // generate color arrays
12400 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)
12402 f = RSurf_FogVertex(v);
12411 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
12413 f = RSurf_FogVertex(v);
12422 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
12429 if (!rsurface.passcolor4f)
12431 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12432 rsurface.passcolor4f_vertexbuffer = 0;
12433 rsurface.passcolor4f_bufferoffset = 0;
12434 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)
12436 f = RSurf_FogVertex(v);
12437 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
12438 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
12439 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
12444 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
12449 if (!rsurface.passcolor4f)
12451 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12452 rsurface.passcolor4f_vertexbuffer = 0;
12453 rsurface.passcolor4f_bufferoffset = 0;
12454 for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12463 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12468 if (!rsurface.passcolor4f)
12470 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12471 rsurface.passcolor4f_vertexbuffer = 0;
12472 rsurface.passcolor4f_bufferoffset = 0;
12473 for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12475 c2[0] = c[0] + r_refdef.scene.ambient;
12476 c2[1] = c[1] + r_refdef.scene.ambient;
12477 c2[2] = c[2] + r_refdef.scene.ambient;
12482 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12485 rsurface.passcolor4f = NULL;
12486 rsurface.passcolor4f_vertexbuffer = 0;
12487 rsurface.passcolor4f_bufferoffset = 0;
12488 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12489 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12490 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12491 GL_Color(r, g, b, a);
12492 R_Mesh_TexBind(0, rsurface.lightmaptexture);
12496 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12498 // TODO: optimize applyfog && applycolor case
12499 // just apply fog if necessary, and tint the fog color array if necessary
12500 rsurface.passcolor4f = NULL;
12501 rsurface.passcolor4f_vertexbuffer = 0;
12502 rsurface.passcolor4f_bufferoffset = 0;
12503 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12504 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12505 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12506 GL_Color(r, g, b, a);
12510 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12513 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12514 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12515 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12516 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12517 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12518 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12519 GL_Color(r, g, b, a);
12523 static void RSurf_DrawBatch_GL11_ClampColor(void)
12528 if (!rsurface.passcolor4f)
12530 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12532 c2[0] = bound(0.0f, c1[0], 1.0f);
12533 c2[1] = bound(0.0f, c1[1], 1.0f);
12534 c2[2] = bound(0.0f, c1[2], 1.0f);
12535 c2[3] = bound(0.0f, c1[3], 1.0f);
12539 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
12549 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12550 rsurface.passcolor4f_vertexbuffer = 0;
12551 rsurface.passcolor4f_bufferoffset = 0;
12552 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)
12554 f = -DotProduct(r_refdef.view.forward, n);
12556 f = f * 0.85 + 0.15; // work around so stuff won't get black
12557 f *= r_refdef.lightmapintensity;
12558 Vector4Set(c, f, f, f, 1);
12562 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12564 RSurf_DrawBatch_GL11_ApplyFakeLight();
12565 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12566 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12567 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12568 GL_Color(r, g, b, a);
12572 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12580 vec3_t ambientcolor;
12581 vec3_t diffusecolor;
12585 VectorCopy(rsurface.modellight_lightdir, lightdir);
12586 f = 0.5f * r_refdef.lightmapintensity;
12587 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12588 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12589 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12590 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12591 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12592 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12594 if (VectorLength2(diffusecolor) > 0)
12596 // q3-style directional shading
12597 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12598 rsurface.passcolor4f_vertexbuffer = 0;
12599 rsurface.passcolor4f_bufferoffset = 0;
12600 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)
12602 if ((f = DotProduct(n, lightdir)) > 0)
12603 VectorMA(ambientcolor, f, diffusecolor, c);
12605 VectorCopy(ambientcolor, c);
12612 *applycolor = false;
12616 *r = ambientcolor[0];
12617 *g = ambientcolor[1];
12618 *b = ambientcolor[2];
12619 rsurface.passcolor4f = NULL;
12620 rsurface.passcolor4f_vertexbuffer = 0;
12621 rsurface.passcolor4f_bufferoffset = 0;
12625 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12627 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12628 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12629 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12630 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12631 GL_Color(r, g, b, a);
12635 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12641 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12643 f = 1 - RSurf_FogVertex(v);
12651 void RSurf_SetupDepthAndCulling(void)
12653 // submodels are biased to avoid z-fighting with world surfaces that they
12654 // may be exactly overlapping (avoids z-fighting artifacts on certain
12655 // doors and things in Quake maps)
12656 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12657 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12658 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12659 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12662 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12664 // transparent sky would be ridiculous
12665 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12667 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12668 skyrenderlater = true;
12669 RSurf_SetupDepthAndCulling();
12670 GL_DepthMask(true);
12671 // LordHavoc: HalfLife maps have freaky skypolys so don't use
12672 // skymasking on them, and Quake3 never did sky masking (unlike
12673 // software Quake and software Quake2), so disable the sky masking
12674 // in Quake3 maps as it causes problems with q3map2 sky tricks,
12675 // and skymasking also looks very bad when noclipping outside the
12676 // level, so don't use it then either.
12677 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12679 R_Mesh_ResetTextureState();
12680 if (skyrendermasked)
12682 R_SetupShader_DepthOrShadow();
12683 // depth-only (masking)
12684 GL_ColorMask(0,0,0,0);
12685 // just to make sure that braindead drivers don't draw
12686 // anything despite that colormask...
12687 GL_BlendFunc(GL_ZERO, GL_ONE);
12688 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12689 if (rsurface.batchvertex3fbuffer)
12690 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12692 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12696 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12698 GL_BlendFunc(GL_ONE, GL_ZERO);
12699 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12700 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12701 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12704 if (skyrendermasked)
12705 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12707 R_Mesh_ResetTextureState();
12708 GL_Color(1, 1, 1, 1);
12711 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12712 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12713 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12715 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12719 // render screenspace normalmap to texture
12720 GL_DepthMask(true);
12721 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12726 // bind lightmap texture
12728 // water/refraction/reflection/camera surfaces have to be handled specially
12729 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
12731 int start, end, startplaneindex;
12732 for (start = 0;start < texturenumsurfaces;start = end)
12734 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12735 if(startplaneindex < 0)
12737 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
12738 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
12742 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12744 // now that we have a batch using the same planeindex, render it
12745 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
12747 // render water or distortion background
12748 GL_DepthMask(true);
12749 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));
12751 // blend surface on top
12752 GL_DepthMask(false);
12753 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12756 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
12758 // render surface with reflection texture as input
12759 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12760 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));
12767 // render surface batch normally
12768 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12769 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12773 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12775 // OpenGL 1.3 path - anything not completely ancient
12776 qboolean applycolor;
12779 const texturelayer_t *layer;
12780 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);
12781 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12783 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12786 int layertexrgbscale;
12787 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12789 if (layerindex == 0)
12790 GL_AlphaTest(true);
12793 GL_AlphaTest(false);
12794 GL_DepthFunc(GL_EQUAL);
12797 GL_DepthMask(layer->depthmask && writedepth);
12798 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12799 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12801 layertexrgbscale = 4;
12802 VectorScale(layer->color, 0.25f, layercolor);
12804 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12806 layertexrgbscale = 2;
12807 VectorScale(layer->color, 0.5f, layercolor);
12811 layertexrgbscale = 1;
12812 VectorScale(layer->color, 1.0f, layercolor);
12814 layercolor[3] = layer->color[3];
12815 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12816 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12817 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12818 switch (layer->type)
12820 case TEXTURELAYERTYPE_LITTEXTURE:
12821 // single-pass lightmapped texture with 2x rgbscale
12822 R_Mesh_TexBind(0, r_texture_white);
12823 R_Mesh_TexMatrix(0, NULL);
12824 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12825 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12826 R_Mesh_TexBind(1, layer->texture);
12827 R_Mesh_TexMatrix(1, &layer->texmatrix);
12828 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12829 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12830 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12831 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12832 else if (FAKELIGHT_ENABLED)
12833 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12834 else if (rsurface.uselightmaptexture)
12835 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12837 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12839 case TEXTURELAYERTYPE_TEXTURE:
12840 // singletexture unlit texture with transparency support
12841 R_Mesh_TexBind(0, layer->texture);
12842 R_Mesh_TexMatrix(0, &layer->texmatrix);
12843 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12844 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12845 R_Mesh_TexBind(1, 0);
12846 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12847 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12849 case TEXTURELAYERTYPE_FOG:
12850 // singletexture fogging
12851 if (layer->texture)
12853 R_Mesh_TexBind(0, layer->texture);
12854 R_Mesh_TexMatrix(0, &layer->texmatrix);
12855 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12856 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12860 R_Mesh_TexBind(0, 0);
12861 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12863 R_Mesh_TexBind(1, 0);
12864 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12865 // generate a color array for the fog pass
12866 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12867 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12871 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12874 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12876 GL_DepthFunc(GL_LEQUAL);
12877 GL_AlphaTest(false);
12881 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12883 // OpenGL 1.1 - crusty old voodoo path
12886 const texturelayer_t *layer;
12887 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);
12888 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12890 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12892 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12894 if (layerindex == 0)
12895 GL_AlphaTest(true);
12898 GL_AlphaTest(false);
12899 GL_DepthFunc(GL_EQUAL);
12902 GL_DepthMask(layer->depthmask && writedepth);
12903 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12904 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12905 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12906 switch (layer->type)
12908 case TEXTURELAYERTYPE_LITTEXTURE:
12909 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12911 // two-pass lit texture with 2x rgbscale
12912 // first the lightmap pass
12913 R_Mesh_TexBind(0, r_texture_white);
12914 R_Mesh_TexMatrix(0, NULL);
12915 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12916 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12917 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12918 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12919 else if (FAKELIGHT_ENABLED)
12920 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12921 else if (rsurface.uselightmaptexture)
12922 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12924 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12925 // then apply the texture to it
12926 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12927 R_Mesh_TexBind(0, layer->texture);
12928 R_Mesh_TexMatrix(0, &layer->texmatrix);
12929 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12930 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12931 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);
12935 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12936 R_Mesh_TexBind(0, layer->texture);
12937 R_Mesh_TexMatrix(0, &layer->texmatrix);
12938 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12939 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12940 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12941 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);
12943 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);
12946 case TEXTURELAYERTYPE_TEXTURE:
12947 // singletexture unlit texture with transparency support
12948 R_Mesh_TexBind(0, layer->texture);
12949 R_Mesh_TexMatrix(0, &layer->texmatrix);
12950 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12951 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12952 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);
12954 case TEXTURELAYERTYPE_FOG:
12955 // singletexture fogging
12956 if (layer->texture)
12958 R_Mesh_TexBind(0, layer->texture);
12959 R_Mesh_TexMatrix(0, &layer->texmatrix);
12960 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12961 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12965 R_Mesh_TexBind(0, 0);
12966 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12968 // generate a color array for the fog pass
12969 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12970 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12974 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12977 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12979 GL_DepthFunc(GL_LEQUAL);
12980 GL_AlphaTest(false);
12984 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12988 r_vertexgeneric_t *batchvertex;
12991 GL_AlphaTest(false);
12992 // R_Mesh_ResetTextureState();
12993 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12995 if(rsurface.texture && rsurface.texture->currentskinframe)
12997 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12998 c[3] *= rsurface.texture->currentalpha;
13008 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
13010 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
13011 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
13012 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
13015 // brighten it up (as texture value 127 means "unlit")
13016 c[0] *= 2 * r_refdef.view.colorscale;
13017 c[1] *= 2 * r_refdef.view.colorscale;
13018 c[2] *= 2 * r_refdef.view.colorscale;
13020 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
13021 c[3] *= r_wateralpha.value;
13023 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
13025 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13026 GL_DepthMask(false);
13028 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
13030 GL_BlendFunc(GL_ONE, GL_ONE);
13031 GL_DepthMask(false);
13033 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
13035 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
13036 GL_DepthMask(false);
13038 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
13040 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
13041 GL_DepthMask(false);
13045 GL_BlendFunc(GL_ONE, GL_ZERO);
13046 GL_DepthMask(writedepth);
13049 if (r_showsurfaces.integer == 3)
13051 rsurface.passcolor4f = NULL;
13053 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
13055 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13057 rsurface.passcolor4f = NULL;
13058 rsurface.passcolor4f_vertexbuffer = 0;
13059 rsurface.passcolor4f_bufferoffset = 0;
13061 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
13063 qboolean applycolor = true;
13066 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13068 r_refdef.lightmapintensity = 1;
13069 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
13070 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
13072 else if (FAKELIGHT_ENABLED)
13074 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13076 r_refdef.lightmapintensity = r_fakelight_intensity.value;
13077 RSurf_DrawBatch_GL11_ApplyFakeLight();
13078 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
13082 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13084 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
13085 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
13086 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
13089 if(!rsurface.passcolor4f)
13090 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
13092 RSurf_DrawBatch_GL11_ApplyAmbient();
13093 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
13094 if(r_refdef.fogenabled)
13095 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
13096 RSurf_DrawBatch_GL11_ClampColor();
13098 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
13099 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13102 else if (!r_refdef.view.showdebug)
13104 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13105 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
13106 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
13108 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13109 Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
13111 R_Mesh_PrepareVertices_Generic_Unlock();
13114 else if (r_showsurfaces.integer == 4)
13116 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13117 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
13118 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
13120 unsigned char c = vi << 3;
13121 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13122 Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
13124 R_Mesh_PrepareVertices_Generic_Unlock();
13127 else if (r_showsurfaces.integer == 2)
13130 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13131 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
13132 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
13134 unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
13135 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
13136 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
13137 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
13138 Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
13139 Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
13140 Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
13142 R_Mesh_PrepareVertices_Generic_Unlock();
13143 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
13147 int texturesurfaceindex;
13149 const msurface_t *surface;
13150 unsigned char surfacecolor4ub[4];
13151 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13152 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
13154 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
13156 surface = texturesurfacelist[texturesurfaceindex];
13157 k = (int)(((size_t)surface) / sizeof(msurface_t));
13158 Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
13159 for (j = 0;j < surface->num_vertices;j++)
13161 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13162 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
13166 R_Mesh_PrepareVertices_Generic_Unlock();
13171 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13174 RSurf_SetupDepthAndCulling();
13175 if (r_showsurfaces.integer)
13177 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13180 switch (vid.renderpath)
13182 case RENDERPATH_GL20:
13183 case RENDERPATH_CGGL:
13184 case RENDERPATH_D3D9:
13185 case RENDERPATH_D3D10:
13186 case RENDERPATH_D3D11:
13187 case RENDERPATH_SOFT:
13188 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13190 case RENDERPATH_GL13:
13191 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13193 case RENDERPATH_GL11:
13194 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13200 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13203 RSurf_SetupDepthAndCulling();
13204 if (r_showsurfaces.integer)
13206 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13209 switch (vid.renderpath)
13211 case RENDERPATH_GL20:
13212 case RENDERPATH_CGGL:
13213 case RENDERPATH_D3D9:
13214 case RENDERPATH_D3D10:
13215 case RENDERPATH_D3D11:
13216 case RENDERPATH_SOFT:
13217 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13219 case RENDERPATH_GL13:
13220 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13222 case RENDERPATH_GL11:
13223 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13229 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13232 int texturenumsurfaces, endsurface;
13233 texture_t *texture;
13234 const msurface_t *surface;
13235 #define MAXBATCH_TRANSPARENTSURFACES 256
13236 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
13238 // if the model is static it doesn't matter what value we give for
13239 // wantnormals and wanttangents, so this logic uses only rules applicable
13240 // to a model, knowing that they are meaningless otherwise
13241 if (ent == r_refdef.scene.worldentity)
13242 RSurf_ActiveWorldEntity();
13243 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13244 RSurf_ActiveModelEntity(ent, false, false, false);
13247 switch (vid.renderpath)
13249 case RENDERPATH_GL20:
13250 case RENDERPATH_CGGL:
13251 case RENDERPATH_D3D9:
13252 case RENDERPATH_D3D10:
13253 case RENDERPATH_D3D11:
13254 case RENDERPATH_SOFT:
13255 RSurf_ActiveModelEntity(ent, true, true, false);
13257 case RENDERPATH_GL13:
13258 case RENDERPATH_GL11:
13259 RSurf_ActiveModelEntity(ent, true, false, false);
13264 if (r_transparentdepthmasking.integer)
13266 qboolean setup = false;
13267 for (i = 0;i < numsurfaces;i = j)
13270 surface = rsurface.modelsurfaces + surfacelist[i];
13271 texture = surface->texture;
13272 rsurface.texture = R_GetCurrentTexture(texture);
13273 rsurface.lightmaptexture = NULL;
13274 rsurface.deluxemaptexture = NULL;
13275 rsurface.uselightmaptexture = false;
13276 // scan ahead until we find a different texture
13277 endsurface = min(i + 1024, numsurfaces);
13278 texturenumsurfaces = 0;
13279 texturesurfacelist[texturenumsurfaces++] = surface;
13280 for (;j < endsurface;j++)
13282 surface = rsurface.modelsurfaces + surfacelist[j];
13283 if (texture != surface->texture)
13285 texturesurfacelist[texturenumsurfaces++] = surface;
13287 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
13289 // render the range of surfaces as depth
13293 GL_ColorMask(0,0,0,0);
13295 GL_DepthTest(true);
13296 GL_BlendFunc(GL_ONE, GL_ZERO);
13297 GL_DepthMask(true);
13298 GL_AlphaTest(false);
13299 // R_Mesh_ResetTextureState();
13300 R_SetupShader_DepthOrShadow();
13302 RSurf_SetupDepthAndCulling();
13303 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
13304 if (rsurface.batchvertex3fbuffer)
13305 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
13307 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
13311 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
13314 for (i = 0;i < numsurfaces;i = j)
13317 surface = rsurface.modelsurfaces + surfacelist[i];
13318 texture = surface->texture;
13319 rsurface.texture = R_GetCurrentTexture(texture);
13320 // scan ahead until we find a different texture
13321 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
13322 texturenumsurfaces = 0;
13323 texturesurfacelist[texturenumsurfaces++] = surface;
13324 if(FAKELIGHT_ENABLED)
13326 rsurface.lightmaptexture = NULL;
13327 rsurface.deluxemaptexture = NULL;
13328 rsurface.uselightmaptexture = false;
13329 for (;j < endsurface;j++)
13331 surface = rsurface.modelsurfaces + surfacelist[j];
13332 if (texture != surface->texture)
13334 texturesurfacelist[texturenumsurfaces++] = surface;
13339 rsurface.lightmaptexture = surface->lightmaptexture;
13340 rsurface.deluxemaptexture = surface->deluxemaptexture;
13341 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
13342 for (;j < endsurface;j++)
13344 surface = rsurface.modelsurfaces + surfacelist[j];
13345 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
13347 texturesurfacelist[texturenumsurfaces++] = surface;
13350 // render the range of surfaces
13351 if (ent == r_refdef.scene.worldentity)
13352 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13354 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13356 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13357 GL_AlphaTest(false);
13360 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
13362 // transparent surfaces get pushed off into the transparent queue
13363 int surfacelistindex;
13364 const msurface_t *surface;
13365 vec3_t tempcenter, center;
13366 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
13368 surface = texturesurfacelist[surfacelistindex];
13369 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
13370 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
13371 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
13372 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
13373 if (queueentity->transparent_offset) // transparent offset
13375 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
13376 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
13377 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
13379 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
13383 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
13385 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
13387 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
13389 RSurf_SetupDepthAndCulling();
13390 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
13391 if (rsurface.batchvertex3fbuffer)
13392 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
13394 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
13398 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
13400 const entity_render_t *queueentity = r_refdef.scene.worldentity;
13403 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13406 if (!rsurface.texture->currentnumlayers)
13408 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13409 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13411 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13413 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13414 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13415 else if (!rsurface.texture->currentnumlayers)
13417 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13419 // in the deferred case, transparent surfaces were queued during prepass
13420 if (!r_shadow_usingdeferredprepass)
13421 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13425 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13426 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13431 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13434 texture_t *texture;
13435 R_FrameData_SetMark();
13436 // break the surface list down into batches by texture and use of lightmapping
13437 for (i = 0;i < numsurfaces;i = j)
13440 // texture is the base texture pointer, rsurface.texture is the
13441 // current frame/skin the texture is directing us to use (for example
13442 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13443 // use skin 1 instead)
13444 texture = surfacelist[i]->texture;
13445 rsurface.texture = R_GetCurrentTexture(texture);
13446 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13448 // if this texture is not the kind we want, skip ahead to the next one
13449 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13453 if(FAKELIGHT_ENABLED || depthonly || prepass)
13455 rsurface.lightmaptexture = NULL;
13456 rsurface.deluxemaptexture = NULL;
13457 rsurface.uselightmaptexture = false;
13458 // simply scan ahead until we find a different texture or lightmap state
13459 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13464 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13465 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13466 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13467 // simply scan ahead until we find a different texture or lightmap state
13468 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13471 // render the range of surfaces
13472 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
13474 R_FrameData_ReturnToMark();
13477 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
13481 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13484 if (!rsurface.texture->currentnumlayers)
13486 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13487 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13489 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13491 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13492 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13493 else if (!rsurface.texture->currentnumlayers)
13495 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13497 // in the deferred case, transparent surfaces were queued during prepass
13498 if (!r_shadow_usingdeferredprepass)
13499 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13503 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13504 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13509 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13512 texture_t *texture;
13513 R_FrameData_SetMark();
13514 // break the surface list down into batches by texture and use of lightmapping
13515 for (i = 0;i < numsurfaces;i = j)
13518 // texture is the base texture pointer, rsurface.texture is the
13519 // current frame/skin the texture is directing us to use (for example
13520 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13521 // use skin 1 instead)
13522 texture = surfacelist[i]->texture;
13523 rsurface.texture = R_GetCurrentTexture(texture);
13524 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13526 // if this texture is not the kind we want, skip ahead to the next one
13527 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13531 if(FAKELIGHT_ENABLED || depthonly || prepass)
13533 rsurface.lightmaptexture = NULL;
13534 rsurface.deluxemaptexture = NULL;
13535 rsurface.uselightmaptexture = false;
13536 // simply scan ahead until we find a different texture or lightmap state
13537 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13542 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13543 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13544 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13545 // simply scan ahead until we find a different texture or lightmap state
13546 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13549 // render the range of surfaces
13550 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
13552 R_FrameData_ReturnToMark();
13555 float locboxvertex3f[6*4*3] =
13557 1,0,1, 1,0,0, 1,1,0, 1,1,1,
13558 0,1,1, 0,1,0, 0,0,0, 0,0,1,
13559 1,1,1, 1,1,0, 0,1,0, 0,1,1,
13560 0,0,1, 0,0,0, 1,0,0, 1,0,1,
13561 0,0,1, 1,0,1, 1,1,1, 0,1,1,
13562 1,0,0, 0,0,0, 0,1,0, 1,1,0
13565 unsigned short locboxelements[6*2*3] =
13570 12,13,14, 12,14,15,
13571 16,17,18, 16,18,19,
13575 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13578 cl_locnode_t *loc = (cl_locnode_t *)ent;
13580 float vertex3f[6*4*3];
13582 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13583 GL_DepthMask(false);
13584 GL_DepthRange(0, 1);
13585 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13586 GL_DepthTest(true);
13587 GL_CullFace(GL_NONE);
13588 R_EntityMatrix(&identitymatrix);
13590 // R_Mesh_ResetTextureState();
13592 i = surfacelist[0];
13593 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13594 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13595 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13596 surfacelist[0] < 0 ? 0.5f : 0.125f);
13598 if (VectorCompare(loc->mins, loc->maxs))
13600 VectorSet(size, 2, 2, 2);
13601 VectorMA(loc->mins, -0.5f, size, mins);
13605 VectorCopy(loc->mins, mins);
13606 VectorSubtract(loc->maxs, loc->mins, size);
13609 for (i = 0;i < 6*4*3;)
13610 for (j = 0;j < 3;j++, i++)
13611 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13613 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13614 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13615 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13618 void R_DrawLocs(void)
13621 cl_locnode_t *loc, *nearestloc;
13623 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13624 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13626 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13627 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13631 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13633 if (decalsystem->decals)
13634 Mem_Free(decalsystem->decals);
13635 memset(decalsystem, 0, sizeof(*decalsystem));
13638 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)
13641 tridecal_t *decals;
13644 // expand or initialize the system
13645 if (decalsystem->maxdecals <= decalsystem->numdecals)
13647 decalsystem_t old = *decalsystem;
13648 qboolean useshortelements;
13649 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13650 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13651 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)));
13652 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13653 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13654 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13655 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13656 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13657 if (decalsystem->numdecals)
13658 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13660 Mem_Free(old.decals);
13661 for (i = 0;i < decalsystem->maxdecals*3;i++)
13662 decalsystem->element3i[i] = i;
13663 if (useshortelements)
13664 for (i = 0;i < decalsystem->maxdecals*3;i++)
13665 decalsystem->element3s[i] = i;
13668 // grab a decal and search for another free slot for the next one
13669 decals = decalsystem->decals;
13670 decal = decalsystem->decals + (i = decalsystem->freedecal++);
13671 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13673 decalsystem->freedecal = i;
13674 if (decalsystem->numdecals <= i)
13675 decalsystem->numdecals = i + 1;
13677 // initialize the decal
13679 decal->triangleindex = triangleindex;
13680 decal->surfaceindex = surfaceindex;
13681 decal->decalsequence = decalsequence;
13682 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13683 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13684 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13685 decal->color4ub[0][3] = 255;
13686 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13687 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13688 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13689 decal->color4ub[1][3] = 255;
13690 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13691 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13692 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13693 decal->color4ub[2][3] = 255;
13694 decal->vertex3f[0][0] = v0[0];
13695 decal->vertex3f[0][1] = v0[1];
13696 decal->vertex3f[0][2] = v0[2];
13697 decal->vertex3f[1][0] = v1[0];
13698 decal->vertex3f[1][1] = v1[1];
13699 decal->vertex3f[1][2] = v1[2];
13700 decal->vertex3f[2][0] = v2[0];
13701 decal->vertex3f[2][1] = v2[1];
13702 decal->vertex3f[2][2] = v2[2];
13703 decal->texcoord2f[0][0] = t0[0];
13704 decal->texcoord2f[0][1] = t0[1];
13705 decal->texcoord2f[1][0] = t1[0];
13706 decal->texcoord2f[1][1] = t1[1];
13707 decal->texcoord2f[2][0] = t2[0];
13708 decal->texcoord2f[2][1] = t2[1];
13711 extern cvar_t cl_decals_bias;
13712 extern cvar_t cl_decals_models;
13713 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13714 // baseparms, parms, temps
13715 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)
13720 const float *vertex3f;
13722 float points[2][9][3];
13729 e = rsurface.modelelement3i + 3*triangleindex;
13731 vertex3f = rsurface.modelvertex3f;
13733 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13735 index = 3*e[cornerindex];
13736 VectorCopy(vertex3f + index, v[cornerindex]);
13739 //TriangleNormal(v[0], v[1], v[2], normal);
13740 //if (DotProduct(normal, localnormal) < 0.0f)
13742 // clip by each of the box planes formed from the projection matrix
13743 // if anything survives, we emit the decal
13744 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]);
13747 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]);
13750 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]);
13753 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]);
13756 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]);
13759 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]);
13762 // some part of the triangle survived, so we have to accept it...
13765 // dynamic always uses the original triangle
13767 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13769 index = 3*e[cornerindex];
13770 VectorCopy(vertex3f + index, v[cornerindex]);
13773 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13775 // convert vertex positions to texcoords
13776 Matrix4x4_Transform(projection, v[cornerindex], temp);
13777 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13778 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13779 // calculate distance fade from the projection origin
13780 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13781 f = bound(0.0f, f, 1.0f);
13782 c[cornerindex][0] = r * f;
13783 c[cornerindex][1] = g * f;
13784 c[cornerindex][2] = b * f;
13785 c[cornerindex][3] = 1.0f;
13786 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13789 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);
13791 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13792 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);
13794 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)
13796 matrix4x4_t projection;
13797 decalsystem_t *decalsystem;
13800 const msurface_t *surface;
13801 const msurface_t *surfaces;
13802 const int *surfacelist;
13803 const texture_t *texture;
13805 int numsurfacelist;
13806 int surfacelistindex;
13809 float localorigin[3];
13810 float localnormal[3];
13811 float localmins[3];
13812 float localmaxs[3];
13815 float planes[6][4];
13818 int bih_triangles_count;
13819 int bih_triangles[256];
13820 int bih_surfaces[256];
13822 decalsystem = &ent->decalsystem;
13823 model = ent->model;
13824 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13826 R_DecalSystem_Reset(&ent->decalsystem);
13830 if (!model->brush.data_leafs && !cl_decals_models.integer)
13832 if (decalsystem->model)
13833 R_DecalSystem_Reset(decalsystem);
13837 if (decalsystem->model != model)
13838 R_DecalSystem_Reset(decalsystem);
13839 decalsystem->model = model;
13841 RSurf_ActiveModelEntity(ent, false, false, false);
13843 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13844 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13845 VectorNormalize(localnormal);
13846 localsize = worldsize*rsurface.inversematrixscale;
13847 localmins[0] = localorigin[0] - localsize;
13848 localmins[1] = localorigin[1] - localsize;
13849 localmins[2] = localorigin[2] - localsize;
13850 localmaxs[0] = localorigin[0] + localsize;
13851 localmaxs[1] = localorigin[1] + localsize;
13852 localmaxs[2] = localorigin[2] + localsize;
13854 //VectorCopy(localnormal, planes[4]);
13855 //VectorVectors(planes[4], planes[2], planes[0]);
13856 AnglesFromVectors(angles, localnormal, NULL, false);
13857 AngleVectors(angles, planes[0], planes[2], planes[4]);
13858 VectorNegate(planes[0], planes[1]);
13859 VectorNegate(planes[2], planes[3]);
13860 VectorNegate(planes[4], planes[5]);
13861 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13862 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13863 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13864 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13865 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13866 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13871 matrix4x4_t forwardprojection;
13872 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13873 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13878 float projectionvector[4][3];
13879 VectorScale(planes[0], ilocalsize, projectionvector[0]);
13880 VectorScale(planes[2], ilocalsize, projectionvector[1]);
13881 VectorScale(planes[4], ilocalsize, projectionvector[2]);
13882 projectionvector[0][0] = planes[0][0] * ilocalsize;
13883 projectionvector[0][1] = planes[1][0] * ilocalsize;
13884 projectionvector[0][2] = planes[2][0] * ilocalsize;
13885 projectionvector[1][0] = planes[0][1] * ilocalsize;
13886 projectionvector[1][1] = planes[1][1] * ilocalsize;
13887 projectionvector[1][2] = planes[2][1] * ilocalsize;
13888 projectionvector[2][0] = planes[0][2] * ilocalsize;
13889 projectionvector[2][1] = planes[1][2] * ilocalsize;
13890 projectionvector[2][2] = planes[2][2] * ilocalsize;
13891 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13892 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13893 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13894 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13898 dynamic = model->surfmesh.isanimated;
13899 numsurfacelist = model->nummodelsurfaces;
13900 surfacelist = model->sortedmodelsurfaces;
13901 surfaces = model->data_surfaces;
13904 bih_triangles_count = -1;
13907 if(model->render_bih.numleafs)
13908 bih = &model->render_bih;
13909 else if(model->collision_bih.numleafs)
13910 bih = &model->collision_bih;
13913 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13914 if(bih_triangles_count == 0)
13916 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13918 if(bih_triangles_count > 0)
13920 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13922 surfaceindex = bih_surfaces[triangleindex];
13923 surface = surfaces + surfaceindex;
13924 texture = surface->texture;
13925 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13927 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13929 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13934 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13936 surfaceindex = surfacelist[surfacelistindex];
13937 surface = surfaces + surfaceindex;
13938 // check cull box first because it rejects more than any other check
13939 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13941 // skip transparent surfaces
13942 texture = surface->texture;
13943 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13945 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13947 numtriangles = surface->num_triangles;
13948 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13949 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13954 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13955 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)
13957 int renderentityindex;
13958 float worldmins[3];
13959 float worldmaxs[3];
13960 entity_render_t *ent;
13962 if (!cl_decals_newsystem.integer)
13965 worldmins[0] = worldorigin[0] - worldsize;
13966 worldmins[1] = worldorigin[1] - worldsize;
13967 worldmins[2] = worldorigin[2] - worldsize;
13968 worldmaxs[0] = worldorigin[0] + worldsize;
13969 worldmaxs[1] = worldorigin[1] + worldsize;
13970 worldmaxs[2] = worldorigin[2] + worldsize;
13972 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13974 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13976 ent = r_refdef.scene.entities[renderentityindex];
13977 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13980 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13984 typedef struct r_decalsystem_splatqueue_s
13986 vec3_t worldorigin;
13987 vec3_t worldnormal;
13993 r_decalsystem_splatqueue_t;
13995 int r_decalsystem_numqueued = 0;
13996 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13998 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)
14000 r_decalsystem_splatqueue_t *queue;
14002 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
14005 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
14006 VectorCopy(worldorigin, queue->worldorigin);
14007 VectorCopy(worldnormal, queue->worldnormal);
14008 Vector4Set(queue->color, r, g, b, a);
14009 Vector4Set(queue->tcrange, s1, t1, s2, t2);
14010 queue->worldsize = worldsize;
14011 queue->decalsequence = cl.decalsequence++;
14014 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
14017 r_decalsystem_splatqueue_t *queue;
14019 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
14020 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);
14021 r_decalsystem_numqueued = 0;
14024 extern cvar_t cl_decals_max;
14025 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
14028 decalsystem_t *decalsystem = &ent->decalsystem;
14035 if (!decalsystem->numdecals)
14038 if (r_showsurfaces.integer)
14041 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
14043 R_DecalSystem_Reset(decalsystem);
14047 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
14048 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
14050 if (decalsystem->lastupdatetime)
14051 frametime = (cl.time - decalsystem->lastupdatetime);
14054 decalsystem->lastupdatetime = cl.time;
14055 decal = decalsystem->decals;
14056 numdecals = decalsystem->numdecals;
14058 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
14060 if (decal->color4ub[0][3])
14062 decal->lived += frametime;
14063 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
14065 memset(decal, 0, sizeof(*decal));
14066 if (decalsystem->freedecal > i)
14067 decalsystem->freedecal = i;
14071 decal = decalsystem->decals;
14072 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
14075 // collapse the array by shuffling the tail decals into the gaps
14078 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
14079 decalsystem->freedecal++;
14080 if (decalsystem->freedecal == numdecals)
14082 decal[decalsystem->freedecal] = decal[--numdecals];
14085 decalsystem->numdecals = numdecals;
14087 if (numdecals <= 0)
14089 // if there are no decals left, reset decalsystem
14090 R_DecalSystem_Reset(decalsystem);
14094 extern skinframe_t *decalskinframe;
14095 static void R_DrawModelDecals_Entity(entity_render_t *ent)
14098 decalsystem_t *decalsystem = &ent->decalsystem;
14107 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
14110 numdecals = decalsystem->numdecals;
14114 if (r_showsurfaces.integer)
14117 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
14119 R_DecalSystem_Reset(decalsystem);
14123 // if the model is static it doesn't matter what value we give for
14124 // wantnormals and wanttangents, so this logic uses only rules applicable
14125 // to a model, knowing that they are meaningless otherwise
14126 if (ent == r_refdef.scene.worldentity)
14127 RSurf_ActiveWorldEntity();
14129 RSurf_ActiveModelEntity(ent, false, false, false);
14131 decalsystem->lastupdatetime = cl.time;
14132 decal = decalsystem->decals;
14134 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
14136 // update vertex positions for animated models
14137 v3f = decalsystem->vertex3f;
14138 c4f = decalsystem->color4f;
14139 t2f = decalsystem->texcoord2f;
14140 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
14142 if (!decal->color4ub[0][3])
14145 if (surfacevisible && !surfacevisible[decal->surfaceindex])
14148 // update color values for fading decals
14149 if (decal->lived >= cl_decals_time.value)
14151 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
14152 alpha *= (1.0f/255.0f);
14155 alpha = 1.0f/255.0f;
14157 c4f[ 0] = decal->color4ub[0][0] * alpha;
14158 c4f[ 1] = decal->color4ub[0][1] * alpha;
14159 c4f[ 2] = decal->color4ub[0][2] * alpha;
14161 c4f[ 4] = decal->color4ub[1][0] * alpha;
14162 c4f[ 5] = decal->color4ub[1][1] * alpha;
14163 c4f[ 6] = decal->color4ub[1][2] * alpha;
14165 c4f[ 8] = decal->color4ub[2][0] * alpha;
14166 c4f[ 9] = decal->color4ub[2][1] * alpha;
14167 c4f[10] = decal->color4ub[2][2] * alpha;
14170 t2f[0] = decal->texcoord2f[0][0];
14171 t2f[1] = decal->texcoord2f[0][1];
14172 t2f[2] = decal->texcoord2f[1][0];
14173 t2f[3] = decal->texcoord2f[1][1];
14174 t2f[4] = decal->texcoord2f[2][0];
14175 t2f[5] = decal->texcoord2f[2][1];
14177 // update vertex positions for animated models
14178 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
14180 e = rsurface.modelelement3i + 3*decal->triangleindex;
14181 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
14182 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
14183 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
14187 VectorCopy(decal->vertex3f[0], v3f);
14188 VectorCopy(decal->vertex3f[1], v3f + 3);
14189 VectorCopy(decal->vertex3f[2], v3f + 6);
14192 if (r_refdef.fogenabled)
14194 alpha = RSurf_FogVertex(v3f);
14195 VectorScale(c4f, alpha, c4f);
14196 alpha = RSurf_FogVertex(v3f + 3);
14197 VectorScale(c4f + 4, alpha, c4f + 4);
14198 alpha = RSurf_FogVertex(v3f + 6);
14199 VectorScale(c4f + 8, alpha, c4f + 8);
14210 r_refdef.stats.drawndecals += numtris;
14212 // now render the decals all at once
14213 // (this assumes they all use one particle font texture!)
14214 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);
14215 // R_Mesh_ResetTextureState();
14216 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
14217 GL_DepthMask(false);
14218 GL_DepthRange(0, 1);
14219 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
14220 GL_DepthTest(true);
14221 GL_CullFace(GL_NONE);
14222 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
14223 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
14224 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
14228 static void R_DrawModelDecals(void)
14232 // fade faster when there are too many decals
14233 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14234 for (i = 0;i < r_refdef.scene.numentities;i++)
14235 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14237 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
14238 for (i = 0;i < r_refdef.scene.numentities;i++)
14239 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14240 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
14242 R_DecalSystem_ApplySplatEntitiesQueue();
14244 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14245 for (i = 0;i < r_refdef.scene.numentities;i++)
14246 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14248 r_refdef.stats.totaldecals += numdecals;
14250 if (r_showsurfaces.integer)
14253 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
14255 for (i = 0;i < r_refdef.scene.numentities;i++)
14257 if (!r_refdef.viewcache.entityvisible[i])
14259 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14260 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
14264 extern cvar_t mod_collision_bih;
14265 void R_DrawDebugModel(void)
14267 entity_render_t *ent = rsurface.entity;
14268 int i, j, k, l, flagsmask;
14269 const msurface_t *surface;
14270 dp_model_t *model = ent->model;
14273 switch(vid.renderpath)
14275 case RENDERPATH_GL11:
14276 case RENDERPATH_GL13:
14277 case RENDERPATH_GL20:
14278 case RENDERPATH_CGGL:
14280 case RENDERPATH_D3D9:
14281 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14283 case RENDERPATH_D3D10:
14284 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14286 case RENDERPATH_D3D11:
14287 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14289 case RENDERPATH_SOFT:
14290 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14294 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
14296 // R_Mesh_ResetTextureState();
14297 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
14298 GL_DepthRange(0, 1);
14299 GL_DepthTest(!r_showdisabledepthtest.integer);
14300 GL_DepthMask(false);
14301 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14303 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
14307 qboolean cullbox = ent == r_refdef.scene.worldentity;
14308 const q3mbrush_t *brush;
14309 const bih_t *bih = &model->collision_bih;
14310 const bih_leaf_t *bihleaf;
14311 float vertex3f[3][3];
14312 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
14314 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
14316 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
14318 switch (bihleaf->type)
14321 brush = model->brush.data_brushes + bihleaf->itemindex;
14322 if (brush->colbrushf && brush->colbrushf->numtriangles)
14324 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);
14325 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
14326 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
14329 case BIH_COLLISIONTRIANGLE:
14330 triangleindex = bihleaf->itemindex;
14331 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
14332 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
14333 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
14334 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);
14335 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14336 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14338 case BIH_RENDERTRIANGLE:
14339 triangleindex = bihleaf->itemindex;
14340 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
14341 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
14342 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
14343 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);
14344 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14345 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14351 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
14353 if (r_showtris.integer || (r_shownormals.value != 0))
14355 if (r_showdisabledepthtest.integer)
14357 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14358 GL_DepthMask(false);
14362 GL_BlendFunc(GL_ONE, GL_ZERO);
14363 GL_DepthMask(true);
14365 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
14367 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
14369 rsurface.texture = R_GetCurrentTexture(surface->texture);
14370 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
14372 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
14373 if (r_showtris.value > 0)
14375 if (!rsurface.texture->currentlayers->depthmask)
14376 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
14377 else if (ent == r_refdef.scene.worldentity)
14378 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
14380 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
14381 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
14382 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
14384 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
14387 if (r_shownormals.value < 0)
14389 qglBegin(GL_LINES);
14390 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14392 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14393 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14394 qglVertex3f(v[0], v[1], v[2]);
14395 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14396 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14397 qglVertex3f(v[0], v[1], v[2]);
14402 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
14404 qglBegin(GL_LINES);
14405 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14407 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14408 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14409 qglVertex3f(v[0], v[1], v[2]);
14410 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14411 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14412 qglVertex3f(v[0], v[1], v[2]);
14416 qglBegin(GL_LINES);
14417 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14419 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14420 GL_Color(0, r_refdef.view.colorscale, 0, 1);
14421 qglVertex3f(v[0], v[1], v[2]);
14422 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
14423 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14424 qglVertex3f(v[0], v[1], v[2]);
14428 qglBegin(GL_LINES);
14429 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14431 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14432 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14433 qglVertex3f(v[0], v[1], v[2]);
14434 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14435 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14436 qglVertex3f(v[0], v[1], v[2]);
14443 rsurface.texture = NULL;
14447 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
14448 int r_maxsurfacelist = 0;
14449 const msurface_t **r_surfacelist = NULL;
14450 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14452 int i, j, endj, flagsmask;
14453 dp_model_t *model = r_refdef.scene.worldmodel;
14454 msurface_t *surfaces;
14455 unsigned char *update;
14456 int numsurfacelist = 0;
14460 if (r_maxsurfacelist < model->num_surfaces)
14462 r_maxsurfacelist = model->num_surfaces;
14464 Mem_Free((msurface_t**)r_surfacelist);
14465 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14468 RSurf_ActiveWorldEntity();
14470 surfaces = model->data_surfaces;
14471 update = model->brushq1.lightmapupdateflags;
14473 // update light styles on this submodel
14474 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14476 model_brush_lightstyleinfo_t *style;
14477 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14479 if (style->value != r_refdef.scene.lightstylevalue[style->style])
14481 int *list = style->surfacelist;
14482 style->value = r_refdef.scene.lightstylevalue[style->style];
14483 for (j = 0;j < style->numsurfaces;j++)
14484 update[list[j]] = true;
14489 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14493 R_DrawDebugModel();
14494 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14498 rsurface.lightmaptexture = NULL;
14499 rsurface.deluxemaptexture = NULL;
14500 rsurface.uselightmaptexture = false;
14501 rsurface.texture = NULL;
14502 rsurface.rtlight = NULL;
14503 numsurfacelist = 0;
14504 // add visible surfaces to draw list
14505 for (i = 0;i < model->nummodelsurfaces;i++)
14507 j = model->sortedmodelsurfaces[i];
14508 if (r_refdef.viewcache.world_surfacevisible[j])
14509 r_surfacelist[numsurfacelist++] = surfaces + j;
14511 // update lightmaps if needed
14512 if (model->brushq1.firstrender)
14514 model->brushq1.firstrender = false;
14515 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14517 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14521 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14522 if (r_refdef.viewcache.world_surfacevisible[j])
14524 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14526 // don't do anything if there were no surfaces
14527 if (!numsurfacelist)
14529 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14532 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14533 GL_AlphaTest(false);
14535 // add to stats if desired
14536 if (r_speeds.integer && !skysurfaces && !depthonly)
14538 r_refdef.stats.world_surfaces += numsurfacelist;
14539 for (j = 0;j < numsurfacelist;j++)
14540 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
14543 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14546 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14548 int i, j, endj, flagsmask;
14549 dp_model_t *model = ent->model;
14550 msurface_t *surfaces;
14551 unsigned char *update;
14552 int numsurfacelist = 0;
14556 if (r_maxsurfacelist < model->num_surfaces)
14558 r_maxsurfacelist = model->num_surfaces;
14560 Mem_Free((msurface_t **)r_surfacelist);
14561 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14564 // if the model is static it doesn't matter what value we give for
14565 // wantnormals and wanttangents, so this logic uses only rules applicable
14566 // to a model, knowing that they are meaningless otherwise
14567 if (ent == r_refdef.scene.worldentity)
14568 RSurf_ActiveWorldEntity();
14569 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14570 RSurf_ActiveModelEntity(ent, false, false, false);
14572 RSurf_ActiveModelEntity(ent, true, true, true);
14573 else if (depthonly)
14575 switch (vid.renderpath)
14577 case RENDERPATH_GL20:
14578 case RENDERPATH_CGGL:
14579 case RENDERPATH_D3D9:
14580 case RENDERPATH_D3D10:
14581 case RENDERPATH_D3D11:
14582 case RENDERPATH_SOFT:
14583 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14585 case RENDERPATH_GL13:
14586 case RENDERPATH_GL11:
14587 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14593 switch (vid.renderpath)
14595 case RENDERPATH_GL20:
14596 case RENDERPATH_CGGL:
14597 case RENDERPATH_D3D9:
14598 case RENDERPATH_D3D10:
14599 case RENDERPATH_D3D11:
14600 case RENDERPATH_SOFT:
14601 RSurf_ActiveModelEntity(ent, true, true, false);
14603 case RENDERPATH_GL13:
14604 case RENDERPATH_GL11:
14605 RSurf_ActiveModelEntity(ent, true, false, false);
14610 surfaces = model->data_surfaces;
14611 update = model->brushq1.lightmapupdateflags;
14613 // update light styles
14614 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14616 model_brush_lightstyleinfo_t *style;
14617 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14619 if (style->value != r_refdef.scene.lightstylevalue[style->style])
14621 int *list = style->surfacelist;
14622 style->value = r_refdef.scene.lightstylevalue[style->style];
14623 for (j = 0;j < style->numsurfaces;j++)
14624 update[list[j]] = true;
14629 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14633 R_DrawDebugModel();
14634 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14638 rsurface.lightmaptexture = NULL;
14639 rsurface.deluxemaptexture = NULL;
14640 rsurface.uselightmaptexture = false;
14641 rsurface.texture = NULL;
14642 rsurface.rtlight = NULL;
14643 numsurfacelist = 0;
14644 // add visible surfaces to draw list
14645 for (i = 0;i < model->nummodelsurfaces;i++)
14646 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14647 // don't do anything if there were no surfaces
14648 if (!numsurfacelist)
14650 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14653 // update lightmaps if needed
14657 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14662 R_BuildLightMap(ent, surfaces + j);
14667 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14669 R_BuildLightMap(ent, surfaces + j);
14670 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14671 GL_AlphaTest(false);
14673 // add to stats if desired
14674 if (r_speeds.integer && !skysurfaces && !depthonly)
14676 r_refdef.stats.entities_surfaces += numsurfacelist;
14677 for (j = 0;j < numsurfacelist;j++)
14678 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14681 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14684 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14686 static texture_t texture;
14687 static msurface_t surface;
14688 const msurface_t *surfacelist = &surface;
14690 // fake enough texture and surface state to render this geometry
14692 texture.update_lastrenderframe = -1; // regenerate this texture
14693 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14694 texture.currentskinframe = skinframe;
14695 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14696 texture.offsetmapping = OFFSETMAPPING_OFF;
14697 texture.offsetscale = 1;
14698 texture.specularscalemod = 1;
14699 texture.specularpowermod = 1;
14701 surface.texture = &texture;
14702 surface.num_triangles = numtriangles;
14703 surface.num_firsttriangle = firsttriangle;
14704 surface.num_vertices = numvertices;
14705 surface.num_firstvertex = firstvertex;
14708 rsurface.texture = R_GetCurrentTexture(surface.texture);
14709 rsurface.lightmaptexture = NULL;
14710 rsurface.deluxemaptexture = NULL;
14711 rsurface.uselightmaptexture = false;
14712 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14715 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)
14717 static msurface_t surface;
14718 const msurface_t *surfacelist = &surface;
14720 // fake enough texture and surface state to render this geometry
14721 surface.texture = texture;
14722 surface.num_triangles = numtriangles;
14723 surface.num_firsttriangle = firsttriangle;
14724 surface.num_vertices = numvertices;
14725 surface.num_firstvertex = firstvertex;
14728 rsurface.texture = R_GetCurrentTexture(surface.texture);
14729 rsurface.lightmaptexture = NULL;
14730 rsurface.deluxemaptexture = NULL;
14731 rsurface.uselightmaptexture = false;
14732 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);