2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
33 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
36 mempool_t *r_main_mempool;
37 rtexturepool_t *r_main_texturepool;
39 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41 static qboolean r_loadnormalmap;
42 static qboolean r_loadgloss;
44 static qboolean r_loaddds;
45 static qboolean r_savedds;
52 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
53 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
54 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
55 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
56 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
57 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
58 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
59 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
61 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
62 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
63 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
64 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
65 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
67 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
68 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
69 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
70 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
71 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
72 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
73 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
74 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
75 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
76 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
77 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
79 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
80 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
81 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
82 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
83 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
84 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
85 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
86 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
87 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
88 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
89 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
90 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
91 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
92 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
93 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
94 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
96 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
97 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
98 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
100 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
101 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
102 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
103 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
104 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
105 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
106 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
107 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
108 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
109 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
110 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
111 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
112 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
113 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
114 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
115 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
117 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
118 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
120 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
121 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
122 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
123 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
124 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
125 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
126 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
127 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
129 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
130 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
132 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
133 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
134 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
138 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
139 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
140 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
142 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
143 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
144 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
145 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
146 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
147 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
148 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
149 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
150 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
151 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
152 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
153 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
154 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
156 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
157 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
158 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
159 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
160 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
161 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
163 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
164 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
165 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
166 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
168 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
169 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
170 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
171 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
172 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
173 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
174 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
176 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
177 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
178 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
179 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
181 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
183 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
185 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
187 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
188 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
189 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
190 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
191 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
192 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
193 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "16", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
195 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
196 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"};
198 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "1", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
200 extern cvar_t v_glslgamma;
202 extern qboolean v_flipped_state;
204 static struct r_bloomstate_s
209 int bloomwidth, bloomheight;
211 int screentexturewidth, screentextureheight;
212 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
214 int bloomtexturewidth, bloomtextureheight;
215 rtexture_t *texture_bloom;
217 // arrays for rendering the screen passes
218 float screentexcoord2f[8];
219 float bloomtexcoord2f[8];
220 float offsettexcoord2f[8];
222 r_viewport_t viewport;
226 r_waterstate_t r_waterstate;
228 /// shadow volume bsp struct with automatically growing nodes buffer
231 rtexture_t *r_texture_blanknormalmap;
232 rtexture_t *r_texture_white;
233 rtexture_t *r_texture_grey128;
234 rtexture_t *r_texture_black;
235 rtexture_t *r_texture_notexture;
236 rtexture_t *r_texture_whitecube;
237 rtexture_t *r_texture_normalizationcube;
238 rtexture_t *r_texture_fogattenuation;
239 rtexture_t *r_texture_fogheighttexture;
240 rtexture_t *r_texture_gammaramps;
241 unsigned int r_texture_gammaramps_serial;
242 //rtexture_t *r_texture_fogintensity;
243 rtexture_t *r_texture_reflectcube;
245 // TODO: hash lookups?
246 typedef struct cubemapinfo_s
253 int r_texture_numcubemaps;
254 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
256 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
257 unsigned int r_numqueries;
258 unsigned int r_maxqueries;
260 typedef struct r_qwskincache_s
262 char name[MAX_QPATH];
263 skinframe_t *skinframe;
267 static r_qwskincache_t *r_qwskincache;
268 static int r_qwskincache_size;
270 /// vertex coordinates for a quad that covers the screen exactly
271 extern const float r_screenvertex3f[12];
272 extern const float r_d3dscreenvertex3f[12];
273 const float r_screenvertex3f[12] =
280 const float r_d3dscreenvertex3f[12] =
288 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
291 for (i = 0;i < verts;i++)
302 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
305 for (i = 0;i < verts;i++)
315 // FIXME: move this to client?
318 if (gamemode == GAME_NEHAHRA)
320 Cvar_Set("gl_fogenable", "0");
321 Cvar_Set("gl_fogdensity", "0.2");
322 Cvar_Set("gl_fogred", "0.3");
323 Cvar_Set("gl_foggreen", "0.3");
324 Cvar_Set("gl_fogblue", "0.3");
326 r_refdef.fog_density = 0;
327 r_refdef.fog_red = 0;
328 r_refdef.fog_green = 0;
329 r_refdef.fog_blue = 0;
330 r_refdef.fog_alpha = 1;
331 r_refdef.fog_start = 0;
332 r_refdef.fog_end = 16384;
333 r_refdef.fog_height = 1<<30;
334 r_refdef.fog_fadedepth = 128;
335 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
338 static void R_BuildBlankTextures(void)
340 unsigned char data[4];
341 data[2] = 128; // normal X
342 data[1] = 128; // normal Y
343 data[0] = 255; // normal Z
344 data[3] = 128; // height
345 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
350 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
355 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
360 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
363 static void R_BuildNoTexture(void)
366 unsigned char pix[16][16][4];
367 // this makes a light grey/dark grey checkerboard texture
368 for (y = 0;y < 16;y++)
370 for (x = 0;x < 16;x++)
372 if ((y < 8) ^ (x < 8))
388 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
391 static void R_BuildWhiteCube(void)
393 unsigned char data[6*1*1*4];
394 memset(data, 255, sizeof(data));
395 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
398 static void R_BuildNormalizationCube(void)
402 vec_t s, t, intensity;
405 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
406 for (side = 0;side < 6;side++)
408 for (y = 0;y < NORMSIZE;y++)
410 for (x = 0;x < NORMSIZE;x++)
412 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
413 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
448 intensity = 127.0f / sqrt(DotProduct(v, v));
449 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
450 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
451 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
452 data[((side*64+y)*64+x)*4+3] = 255;
456 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
460 static void R_BuildFogTexture(void)
464 unsigned char data1[FOGWIDTH][4];
465 //unsigned char data2[FOGWIDTH][4];
468 r_refdef.fogmasktable_start = r_refdef.fog_start;
469 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
470 r_refdef.fogmasktable_range = r_refdef.fogrange;
471 r_refdef.fogmasktable_density = r_refdef.fog_density;
473 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
474 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
476 d = (x * r - r_refdef.fogmasktable_start);
477 if(developer_extra.integer)
478 Con_DPrintf("%f ", d);
480 if (r_fog_exp2.integer)
481 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
483 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
484 if(developer_extra.integer)
485 Con_DPrintf(" : %f ", alpha);
486 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
487 if(developer_extra.integer)
488 Con_DPrintf(" = %f\n", alpha);
489 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
492 for (x = 0;x < FOGWIDTH;x++)
494 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
499 //data2[x][0] = 255 - b;
500 //data2[x][1] = 255 - b;
501 //data2[x][2] = 255 - b;
504 if (r_texture_fogattenuation)
506 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
507 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
511 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
512 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
516 static void R_BuildFogHeightTexture(void)
518 unsigned char *inpixels;
526 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
527 if (r_refdef.fogheighttexturename[0])
528 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
531 r_refdef.fog_height_tablesize = 0;
532 if (r_texture_fogheighttexture)
533 R_FreeTexture(r_texture_fogheighttexture);
534 r_texture_fogheighttexture = NULL;
535 if (r_refdef.fog_height_table2d)
536 Mem_Free(r_refdef.fog_height_table2d);
537 r_refdef.fog_height_table2d = NULL;
538 if (r_refdef.fog_height_table1d)
539 Mem_Free(r_refdef.fog_height_table1d);
540 r_refdef.fog_height_table1d = NULL;
544 r_refdef.fog_height_tablesize = size;
545 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
546 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
547 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
549 // LordHavoc: now the magic - what is that table2d for? it is a cooked
550 // average fog color table accounting for every fog layer between a point
551 // and the camera. (Note: attenuation is handled separately!)
552 for (y = 0;y < size;y++)
554 for (x = 0;x < size;x++)
560 for (j = x;j <= y;j++)
562 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
568 for (j = x;j >= y;j--)
570 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
575 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
576 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
577 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
578 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
581 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
584 //=======================================================================================================================================================
586 static const char *builtinshaderstring =
587 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
588 "// written by Forest 'LordHavoc' Hale\n"
589 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
591 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
594 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
595 "#define USELIGHTMAP\n"
597 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
598 "#define USEEYEVECTOR\n"
601 "#ifdef USESHADOWMAP2D\n"
602 "# ifdef GL_EXT_gpu_shader4\n"
603 "# extension GL_EXT_gpu_shader4 : enable\n"
605 "# ifdef GL_ARB_texture_gather\n"
606 "# extension GL_ARB_texture_gather : enable\n"
608 "# ifdef GL_AMD_texture_texture4\n"
609 "# extension GL_AMD_texture_texture4 : enable\n"
614 "//#ifdef USESHADOWSAMPLER\n"
615 "//# extension GL_ARB_shadow : enable\n"
618 "//#ifdef __GLSL_CG_DATA_TYPES\n"
619 "//# define myhalf half\n"
620 "//# define myhalf2 half2\n"
621 "//# define myhalf3 half3\n"
622 "//# define myhalf4 half4\n"
624 "# define myhalf float\n"
625 "# define myhalf2 vec2\n"
626 "# define myhalf3 vec3\n"
627 "# define myhalf4 vec4\n"
630 "#ifdef VERTEX_SHADER\n"
631 "uniform mat4 ModelViewProjectionMatrix;\n"
634 "#ifdef MODE_DEPTH_OR_SHADOW\n"
635 "#ifdef VERTEX_SHADER\n"
638 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
641 "#else // !MODE_DEPTH_ORSHADOW\n"
646 "#ifdef MODE_SHOWDEPTH\n"
647 "#ifdef VERTEX_SHADER\n"
650 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
651 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
655 "#ifdef FRAGMENT_SHADER\n"
658 " gl_FragColor = gl_Color;\n"
661 "#else // !MODE_SHOWDEPTH\n"
666 "#ifdef MODE_POSTPROCESS\n"
667 "varying vec2 TexCoord1;\n"
668 "varying vec2 TexCoord2;\n"
670 "#ifdef VERTEX_SHADER\n"
673 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
674 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
676 " TexCoord2 = gl_MultiTexCoord4.xy;\n"
681 "#ifdef FRAGMENT_SHADER\n"
682 "uniform sampler2D Texture_First;\n"
684 "uniform sampler2D Texture_Second;\n"
685 "uniform vec4 BloomColorSubtract;\n"
687 "#ifdef USEGAMMARAMPS\n"
688 "uniform sampler2D Texture_GammaRamps;\n"
690 "#ifdef USESATURATION\n"
691 "uniform float Saturation;\n"
693 "#ifdef USEVIEWTINT\n"
694 "uniform vec4 ViewTintColor;\n"
696 "//uncomment these if you want to use them:\n"
697 "uniform vec4 UserVec1;\n"
698 "uniform vec4 UserVec2;\n"
699 "// uniform vec4 UserVec3;\n"
700 "// uniform vec4 UserVec4;\n"
701 "// uniform float ClientTime;\n"
702 "uniform vec2 PixelSize;\n"
705 " gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
707 " gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
709 "#ifdef USEVIEWTINT\n"
710 " gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
713 "#ifdef USEPOSTPROCESSING\n"
714 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
715 "// 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"
716 " float sobel = 1.0;\n"
717 " // vec2 ts = textureSize(Texture_First, 0);\n"
718 " // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
719 " vec2 px = PixelSize;\n"
720 " vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
721 " vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, 0.0)).rgb;\n"
722 " vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
723 " vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
724 " vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x, 0.0)).rgb;\n"
725 " vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
726 " vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
727 " vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2( 0.0,-px.y)).rgb;\n"
728 " vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
729 " vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
730 " vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2( 0.0, px.y)).rgb;\n"
731 " vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
732 " float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
733 " float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
734 " float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
735 " float px4 = 1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
736 " float px5 = 2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
737 " float px6 = 1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
738 " float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
739 " float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
740 " float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
741 " float py4 = 1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
742 " float py5 = 2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
743 " float py6 = 1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
744 " sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
745 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
746 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
747 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
748 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
749 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
750 " gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
751 " gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
754 "#ifdef USESATURATION\n"
755 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
756 " float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
757 " // 'vampire sight' effect, wheres red is compensated\n"
758 " #ifdef SATURATION_REDCOMPENSATE\n"
759 " float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
760 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
761 " gl_FragColor.r += rboost;\n"
763 " // normal desaturation\n"
764 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
765 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
769 "#ifdef USEGAMMARAMPS\n"
770 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
771 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
772 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
776 "#else // !MODE_POSTPROCESS\n"
781 "#ifdef MODE_GENERIC\n"
782 "#ifdef USEDIFFUSE\n"
783 "varying vec2 TexCoord1;\n"
785 "#ifdef USESPECULAR\n"
786 "varying vec2 TexCoord2;\n"
788 "#ifdef VERTEX_SHADER\n"
791 " gl_FrontColor = gl_Color;\n"
792 "#ifdef USEDIFFUSE\n"
793 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
795 "#ifdef USESPECULAR\n"
796 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
798 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
802 "#ifdef FRAGMENT_SHADER\n"
803 "#ifdef USEDIFFUSE\n"
804 "uniform sampler2D Texture_First;\n"
806 "#ifdef USESPECULAR\n"
807 "uniform sampler2D Texture_Second;\n"
812 " gl_FragColor = gl_Color;\n"
813 "#ifdef USEDIFFUSE\n"
814 " gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
817 "#ifdef USESPECULAR\n"
818 " vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
819 "# ifdef USECOLORMAPPING\n"
820 " gl_FragColor *= tex2;\n"
823 " gl_FragColor += tex2;\n"
825 "# ifdef USEVERTEXTEXTUREBLEND\n"
826 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
831 "#else // !MODE_GENERIC\n"
836 "#ifdef MODE_BLOOMBLUR\n"
837 "varying TexCoord;\n"
838 "#ifdef VERTEX_SHADER\n"
841 " gl_FrontColor = gl_Color;\n"
842 " TexCoord = gl_MultiTexCoord0.xy;\n"
843 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
847 "#ifdef FRAGMENT_SHADER\n"
848 "uniform sampler2D Texture_First;\n"
849 "uniform vec4 BloomBlur_Parameters;\n"
854 " vec2 tc = TexCoord;\n"
855 " vec3 color = texture2D(Texture_First, tc).rgb;\n"
856 " tc += BloomBlur_Parameters.xy;\n"
857 " for (i = 1;i < SAMPLES;i++)\n"
859 " color += texture2D(Texture_First, tc).rgb;\n"
860 " tc += BloomBlur_Parameters.xy;\n"
862 " gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
865 "#else // !MODE_BLOOMBLUR\n"
866 "#ifdef MODE_REFRACTION\n"
867 "varying vec2 TexCoord;\n"
868 "varying vec4 ModelViewProjectionPosition;\n"
869 "uniform mat4 TexMatrix;\n"
870 "#ifdef VERTEX_SHADER\n"
874 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
875 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
876 " ModelViewProjectionPosition = gl_Position;\n"
880 "#ifdef FRAGMENT_SHADER\n"
881 "uniform sampler2D Texture_Normal;\n"
882 "uniform sampler2D Texture_Refraction;\n"
883 "uniform sampler2D Texture_Reflection;\n"
885 "uniform vec4 DistortScaleRefractReflect;\n"
886 "uniform vec4 ScreenScaleRefractReflect;\n"
887 "uniform vec4 ScreenCenterRefractReflect;\n"
888 "uniform vec4 RefractColor;\n"
889 "uniform vec4 ReflectColor;\n"
890 "uniform float ReflectFactor;\n"
891 "uniform float ReflectOffset;\n"
895 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
896 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
897 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
898 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
899 " // FIXME temporary hack to detect the case that the reflection\n"
900 " // gets blackened at edges due to leaving the area that contains actual\n"
902 " // Remove this 'ack once we have a better way to stop this thing from\n"
904 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
905 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
906 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
907 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
908 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
909 " gl_FragColor = vec4(texture2D(Texture_Refraction, ScreenTexCoord).rgb, 1.0) * RefractColor;\n"
912 "#else // !MODE_REFRACTION\n"
917 "#ifdef MODE_WATER\n"
918 "varying vec2 TexCoord;\n"
919 "varying vec3 EyeVector;\n"
920 "varying vec4 ModelViewProjectionPosition;\n"
921 "#ifdef VERTEX_SHADER\n"
922 "uniform vec3 EyePosition;\n"
923 "uniform mat4 TexMatrix;\n"
927 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
928 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
929 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
930 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
931 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
932 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
933 " ModelViewProjectionPosition = gl_Position;\n"
937 "#ifdef FRAGMENT_SHADER\n"
938 "uniform sampler2D Texture_Normal;\n"
939 "uniform sampler2D Texture_Refraction;\n"
940 "uniform sampler2D Texture_Reflection;\n"
942 "uniform vec4 DistortScaleRefractReflect;\n"
943 "uniform vec4 ScreenScaleRefractReflect;\n"
944 "uniform vec4 ScreenCenterRefractReflect;\n"
945 "uniform vec4 RefractColor;\n"
946 "uniform vec4 ReflectColor;\n"
947 "uniform float ReflectFactor;\n"
948 "uniform float ReflectOffset;\n"
949 "uniform float ClientTime;\n"
950 "#ifdef USENORMALMAPSCROLLBLEND\n"
951 "uniform vec2 NormalmapScrollBlend;\n"
956 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
957 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
958 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
959 " //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
960 " // slight water animation via 2 layer scrolling (todo: tweak)\n"
961 " #ifdef USENORMALMAPSCROLLBLEND\n"
962 " vec3 normal = texture2D(Texture_Normal, (TexCoord + vec2(0.08, 0.08)*ClientTime*NormalmapScrollBlend.x*0.5)*NormalmapScrollBlend.y).rgb - vec3(1.0);\n"
963 " normal += texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime*NormalmapScrollBlend.x)*NormalmapScrollBlend.y*0.75).rgb;\n"
964 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(normal) + vec3(0.15)).xyxy * DistortScaleRefractReflect;\n"
966 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
968 " // FIXME temporary hack to detect the case that the reflection\n"
969 " // gets blackened at edges due to leaving the area that contains actual\n"
971 " // Remove this 'ack once we have a better way to stop this thing from\n"
973 " float f1 = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, 0.01)).rgb) / 0.002);\n"
974 " f1 *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, -0.01)).rgb) / 0.002);\n"
975 " f1 *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, 0.01)).rgb) / 0.002);\n"
976 " f1 *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, -0.01)).rgb) / 0.002);\n"
977 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f1);\n"
978 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, 0.005)).rgb) / 0.002);\n"
979 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, -0.005)).rgb) / 0.002);\n"
980 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, 0.005)).rgb) / 0.002);\n"
981 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, -0.005)).rgb) / 0.002);\n"
982 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
983 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
984 " gl_FragColor = mix(vec4(texture2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, vec4(texture2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
985 " gl_FragColor.a = f1 + 0.5;\n"
988 "#else // !MODE_WATER\n"
993 "// common definitions between vertex shader and fragment shader:\n"
995 "varying vec2 TexCoord;\n"
996 "#ifdef USEVERTEXTEXTUREBLEND\n"
997 "varying vec2 TexCoord2;\n"
999 "#ifdef USELIGHTMAP\n"
1000 "varying vec2 TexCoordLightmap;\n"
1003 "#ifdef MODE_LIGHTSOURCE\n"
1004 "varying vec3 CubeVector;\n"
1007 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
1008 "varying vec3 LightVector;\n"
1011 "#ifdef USEEYEVECTOR\n"
1012 "varying vec3 EyeVector;\n"
1015 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
1018 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
1019 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
1020 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
1021 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
1024 "#ifdef USEREFLECTION\n"
1025 "varying vec4 ModelViewProjectionPosition;\n"
1027 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1028 "uniform vec3 LightPosition;\n"
1029 "varying vec4 ModelViewPosition;\n"
1032 "#ifdef MODE_LIGHTSOURCE\n"
1033 "uniform vec3 LightPosition;\n"
1035 "uniform vec3 EyePosition;\n"
1036 "#ifdef MODE_LIGHTDIRECTION\n"
1037 "uniform vec3 LightDir;\n"
1039 "uniform vec4 FogPlane;\n"
1041 "#ifdef USESHADOWMAPORTHO\n"
1042 "varying vec3 ShadowMapTC;\n"
1049 "// 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"
1051 "// fragment shader specific:\n"
1052 "#ifdef FRAGMENT_SHADER\n"
1054 "uniform sampler2D Texture_Normal;\n"
1055 "uniform sampler2D Texture_Color;\n"
1056 "uniform sampler2D Texture_Gloss;\n"
1058 "uniform sampler2D Texture_Glow;\n"
1060 "#ifdef USEVERTEXTEXTUREBLEND\n"
1061 "uniform sampler2D Texture_SecondaryNormal;\n"
1062 "uniform sampler2D Texture_SecondaryColor;\n"
1063 "uniform sampler2D Texture_SecondaryGloss;\n"
1065 "uniform sampler2D Texture_SecondaryGlow;\n"
1068 "#ifdef USECOLORMAPPING\n"
1069 "uniform sampler2D Texture_Pants;\n"
1070 "uniform sampler2D Texture_Shirt;\n"
1073 "#ifdef USEFOGHEIGHTTEXTURE\n"
1074 "uniform sampler2D Texture_FogHeightTexture;\n"
1076 "uniform sampler2D Texture_FogMask;\n"
1078 "#ifdef USELIGHTMAP\n"
1079 "uniform sampler2D Texture_Lightmap;\n"
1081 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1082 "uniform sampler2D Texture_Deluxemap;\n"
1084 "#ifdef USEREFLECTION\n"
1085 "uniform sampler2D Texture_Reflection;\n"
1088 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1089 "uniform sampler2D Texture_ScreenDepth;\n"
1090 "uniform sampler2D Texture_ScreenNormalMap;\n"
1092 "#ifdef USEDEFERREDLIGHTMAP\n"
1093 "uniform sampler2D Texture_ScreenDiffuse;\n"
1094 "uniform sampler2D Texture_ScreenSpecular;\n"
1097 "uniform myhalf3 Color_Pants;\n"
1098 "uniform myhalf3 Color_Shirt;\n"
1099 "uniform myhalf3 FogColor;\n"
1102 "uniform float FogRangeRecip;\n"
1103 "uniform float FogPlaneViewDist;\n"
1104 "uniform float FogHeightFade;\n"
1105 "vec3 FogVertex(vec3 surfacecolor)\n"
1107 " vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1108 " float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1110 "#ifdef USEFOGHEIGHTTEXTURE\n"
1111 " vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1112 " fogfrac = fogheightpixel.a;\n"
1113 " return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1115 "# ifdef USEFOGOUTSIDE\n"
1116 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1118 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1120 " return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1125 "#ifdef USEOFFSETMAPPING\n"
1126 "uniform float OffsetMapping_Scale;\n"
1127 "vec2 OffsetMapping(vec2 TexCoord)\n"
1129 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1130 " // 14 sample relief mapping: linear search and then binary search\n"
1131 " // this basically steps forward a small amount repeatedly until it finds\n"
1132 " // itself inside solid, then jitters forward and back using decreasing\n"
1133 " // amounts to find the impact\n"
1134 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1135 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1136 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1137 " vec3 RT = vec3(TexCoord, 1);\n"
1138 " OffsetVector *= 0.1;\n"
1139 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1140 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1141 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1142 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1143 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1144 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1145 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1146 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1147 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1148 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
1149 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
1150 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
1151 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
1152 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1155 " // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1156 " // this basically moves forward the full distance, and then backs up based\n"
1157 " // on height of samples\n"
1158 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1159 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1160 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1161 " TexCoord += OffsetVector;\n"
1162 " OffsetVector *= 0.5;\n"
1163 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1164 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1165 " return TexCoord;\n"
1168 "#endif // USEOFFSETMAPPING\n"
1170 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1171 "uniform sampler2D Texture_Attenuation;\n"
1172 "uniform samplerCube Texture_Cube;\n"
1175 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1177 "#ifdef USESHADOWMAP2D\n"
1178 "# ifdef USESHADOWSAMPLER\n"
1179 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1181 "uniform sampler2D Texture_ShadowMap2D;\n"
1185 "#ifdef USESHADOWMAPVSDCT\n"
1186 "uniform samplerCube Texture_CubeProjection;\n"
1189 "#if defined(USESHADOWMAP2D)\n"
1190 "uniform vec2 ShadowMap_TextureScale;\n"
1191 "uniform vec4 ShadowMap_Parameters;\n"
1194 "#if defined(USESHADOWMAP2D)\n"
1195 "# ifdef USESHADOWMAPORTHO\n"
1196 "# define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1198 "# ifdef USESHADOWMAPVSDCT\n"
1199 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1201 " vec3 adir = abs(dir);\n"
1202 " vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1203 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1204 " return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1207 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1209 " vec3 adir = abs(dir);\n"
1210 " float ma = adir.z;\n"
1211 " vec4 proj = vec4(dir, 2.5);\n"
1212 " if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1213 " if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1214 " vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1215 " 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"
1219 "#endif // defined(USESHADOWMAP2D)\n"
1221 "# ifdef USESHADOWMAP2D\n"
1222 "float ShadowMapCompare(vec3 dir)\n"
1224 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1227 "# ifdef USESHADOWSAMPLER\n"
1228 "# ifdef USESHADOWMAPPCF\n"
1229 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1230 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1231 " 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"
1233 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1236 "# ifdef USESHADOWMAPPCF\n"
1237 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1238 "# ifdef GL_ARB_texture_gather\n"
1239 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1241 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1243 " vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1244 "# if USESHADOWMAPPCF > 1\n"
1245 " vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1246 " vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1247 " vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1248 " vec4 group4 = step(shadowmaptc.z, texval(-2.0, 0.0));\n"
1249 " vec4 group5 = step(shadowmaptc.z, texval( 0.0, 0.0));\n"
1250 " vec4 group6 = step(shadowmaptc.z, texval( 2.0, 0.0));\n"
1251 " vec4 group7 = step(shadowmaptc.z, texval(-2.0, 2.0));\n"
1252 " vec4 group8 = step(shadowmaptc.z, texval( 0.0, 2.0));\n"
1253 " vec4 group9 = step(shadowmaptc.z, texval( 2.0, 2.0));\n"
1254 " vec4 locols = vec4(group1.ab, group3.ab);\n"
1255 " vec4 hicols = vec4(group7.rg, group9.rg);\n"
1256 " locols.yz += group2.ab;\n"
1257 " hicols.yz += group8.rg;\n"
1258 " vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1259 " vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1260 " mix(locols, hicols, offset.y);\n"
1261 " vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1262 " cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1263 " f = dot(cols, vec4(1.0/25.0));\n"
1265 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1266 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1267 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1268 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1269 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1270 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1271 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1274 "# ifdef GL_EXT_gpu_shader4\n"
1275 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1277 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1279 "# if USESHADOWMAPPCF > 1\n"
1280 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1281 " center *= ShadowMap_TextureScale;\n"
1282 " 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"
1283 " 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"
1284 " 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"
1285 " 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"
1286 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1287 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1289 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1290 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1291 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1292 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1293 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1294 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1298 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1301 "# ifdef USESHADOWMAPORTHO\n"
1302 " return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1308 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1309 "#endif // FRAGMENT_SHADER\n"
1314 "#ifdef MODE_DEFERREDGEOMETRY\n"
1315 "#ifdef VERTEX_SHADER\n"
1316 "uniform mat4 TexMatrix;\n"
1317 "#ifdef USEVERTEXTEXTUREBLEND\n"
1318 "uniform mat4 BackgroundTexMatrix;\n"
1320 "uniform mat4 ModelViewMatrix;\n"
1323 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1324 "#ifdef USEVERTEXTEXTUREBLEND\n"
1325 " gl_FrontColor = gl_Color;\n"
1326 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1329 " // transform unnormalized eye direction into tangent space\n"
1330 "#ifdef USEOFFSETMAPPING\n"
1331 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1332 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1333 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1334 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1337 " VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1338 " VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1339 " VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1340 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1342 "#endif // VERTEX_SHADER\n"
1344 "#ifdef FRAGMENT_SHADER\n"
1347 "#ifdef USEOFFSETMAPPING\n"
1348 " // apply offsetmapping\n"
1349 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1350 "#define TexCoord TexCoordOffset\n"
1353 "#ifdef USEALPHAKILL\n"
1354 " if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1358 "#ifdef USEVERTEXTEXTUREBLEND\n"
1359 " float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1360 " float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1361 " //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1362 " //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1365 "#ifdef USEVERTEXTEXTUREBLEND\n"
1366 " vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1367 " float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1369 " vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1370 " float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1373 " gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1375 "#endif // FRAGMENT_SHADER\n"
1376 "#else // !MODE_DEFERREDGEOMETRY\n"
1381 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1382 "#ifdef VERTEX_SHADER\n"
1383 "uniform mat4 ModelViewMatrix;\n"
1386 " ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1387 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1389 "#endif // VERTEX_SHADER\n"
1391 "#ifdef FRAGMENT_SHADER\n"
1392 "uniform mat4 ViewToLight;\n"
1393 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1394 "uniform vec2 ScreenToDepth;\n"
1395 "uniform myhalf3 DeferredColor_Ambient;\n"
1396 "uniform myhalf3 DeferredColor_Diffuse;\n"
1397 "#ifdef USESPECULAR\n"
1398 "uniform myhalf3 DeferredColor_Specular;\n"
1399 "uniform myhalf SpecularPower;\n"
1401 "uniform myhalf2 PixelToScreenTexCoord;\n"
1404 " // calculate viewspace pixel position\n"
1405 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1407 " position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1408 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1409 " // decode viewspace pixel normal\n"
1410 " myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1411 " myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1412 " // surfacenormal = pixel normal in viewspace\n"
1413 " // LightVector = pixel to light in viewspace\n"
1414 " // CubeVector = position in lightspace\n"
1415 " // eyevector = pixel to view in viewspace\n"
1416 " vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1417 " myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1418 "#ifdef USEDIFFUSE\n"
1419 " // calculate diffuse shading\n"
1420 " myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1421 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1423 "#ifdef USESPECULAR\n"
1424 " // calculate directional shading\n"
1425 " vec3 eyevector = position * -1.0;\n"
1426 "# ifdef USEEXACTSPECULARMATH\n"
1427 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1429 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1430 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1434 "#if defined(USESHADOWMAP2D)\n"
1435 " fade *= ShadowMapCompare(CubeVector);\n"
1438 "#ifdef USEDIFFUSE\n"
1439 " gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1441 " gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1443 "#ifdef USESPECULAR\n"
1444 " gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1446 " gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1449 "# ifdef USECUBEFILTER\n"
1450 " vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1451 " gl_FragData[0].rgb *= cubecolor;\n"
1452 " gl_FragData[1].rgb *= cubecolor;\n"
1455 "#endif // FRAGMENT_SHADER\n"
1456 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1461 "#ifdef VERTEX_SHADER\n"
1462 "uniform mat4 TexMatrix;\n"
1463 "#ifdef USEVERTEXTEXTUREBLEND\n"
1464 "uniform mat4 BackgroundTexMatrix;\n"
1466 "#ifdef MODE_LIGHTSOURCE\n"
1467 "uniform mat4 ModelToLight;\n"
1469 "#ifdef USESHADOWMAPORTHO\n"
1470 "uniform mat4 ShadowMapMatrix;\n"
1474 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1475 " gl_FrontColor = gl_Color;\n"
1477 " // copy the surface texcoord\n"
1478 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1479 "#ifdef USEVERTEXTEXTUREBLEND\n"
1480 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1482 "#ifdef USELIGHTMAP\n"
1483 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1486 "#ifdef MODE_LIGHTSOURCE\n"
1487 " // transform vertex position into light attenuation/cubemap space\n"
1488 " // (-1 to +1 across the light box)\n"
1489 " CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1491 "# ifdef USEDIFFUSE\n"
1492 " // transform unnormalized light direction into tangent space\n"
1493 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
1494 " // normalize it per pixel)\n"
1495 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1496 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1497 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1498 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1502 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1503 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1504 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1505 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1508 " // transform unnormalized eye direction into tangent space\n"
1509 "#ifdef USEEYEVECTOR\n"
1510 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1511 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1512 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1513 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1517 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1518 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1521 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1522 " VectorS = gl_MultiTexCoord1.xyz;\n"
1523 " VectorT = gl_MultiTexCoord2.xyz;\n"
1524 " VectorR = gl_MultiTexCoord3.xyz;\n"
1527 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1528 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1530 "#ifdef USESHADOWMAPORTHO\n"
1531 " ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1534 "#ifdef USEREFLECTION\n"
1535 " ModelViewProjectionPosition = gl_Position;\n"
1538 "#endif // VERTEX_SHADER\n"
1543 "#ifdef FRAGMENT_SHADER\n"
1544 "#ifdef USEDEFERREDLIGHTMAP\n"
1545 "uniform myhalf2 PixelToScreenTexCoord;\n"
1546 "uniform myhalf3 DeferredMod_Diffuse;\n"
1547 "uniform myhalf3 DeferredMod_Specular;\n"
1549 "uniform myhalf3 Color_Ambient;\n"
1550 "uniform myhalf3 Color_Diffuse;\n"
1551 "uniform myhalf3 Color_Specular;\n"
1552 "uniform myhalf SpecularPower;\n"
1554 "uniform myhalf3 Color_Glow;\n"
1556 "uniform myhalf Alpha;\n"
1557 "#ifdef USEREFLECTION\n"
1558 "uniform vec4 DistortScaleRefractReflect;\n"
1559 "uniform vec4 ScreenScaleRefractReflect;\n"
1560 "uniform vec4 ScreenCenterRefractReflect;\n"
1561 "uniform myhalf4 ReflectColor;\n"
1563 "#ifdef USEREFLECTCUBE\n"
1564 "uniform mat4 ModelToReflectCube;\n"
1565 "uniform sampler2D Texture_ReflectMask;\n"
1566 "uniform samplerCube Texture_ReflectCube;\n"
1568 "#ifdef MODE_LIGHTDIRECTION\n"
1569 "uniform myhalf3 LightColor;\n"
1571 "#ifdef MODE_LIGHTSOURCE\n"
1572 "uniform myhalf3 LightColor;\n"
1576 "#ifdef USEOFFSETMAPPING\n"
1577 " // apply offsetmapping\n"
1578 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1579 "#define TexCoord TexCoordOffset\n"
1582 " // combine the diffuse textures (base, pants, shirt)\n"
1583 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1584 "#ifdef USEALPHAKILL\n"
1585 " if (color.a < 0.5)\n"
1588 " color.a *= Alpha;\n"
1589 "#ifdef USECOLORMAPPING\n"
1590 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1592 "#ifdef USEVERTEXTEXTUREBLEND\n"
1593 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1594 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1595 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1596 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1598 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1601 " // get the surface normal\n"
1602 "#ifdef USEVERTEXTEXTUREBLEND\n"
1603 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1605 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1608 " // get the material colors\n"
1609 " myhalf3 diffusetex = color.rgb;\n"
1610 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1611 "# ifdef USEVERTEXTEXTUREBLEND\n"
1612 " myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1614 " myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1618 "#ifdef USEREFLECTCUBE\n"
1619 " vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1620 " vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1621 " vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1622 " diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1628 "#ifdef MODE_LIGHTSOURCE\n"
1629 " // light source\n"
1630 "#ifdef USEDIFFUSE\n"
1631 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1632 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1633 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1634 "#ifdef USESPECULAR\n"
1635 "#ifdef USEEXACTSPECULARMATH\n"
1636 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1638 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1639 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1641 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1644 " color.rgb = diffusetex * Color_Ambient;\n"
1646 " color.rgb *= LightColor;\n"
1647 " color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1648 "#if defined(USESHADOWMAP2D)\n"
1649 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1651 "# ifdef USECUBEFILTER\n"
1652 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1654 "#endif // MODE_LIGHTSOURCE\n"
1659 "#ifdef MODE_LIGHTDIRECTION\n"
1661 "#ifdef USEDIFFUSE\n"
1662 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1664 "#define lightcolor LightColor\n"
1665 "#endif // MODE_LIGHTDIRECTION\n"
1666 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1668 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1669 " myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1670 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1671 " // convert modelspace light vector to tangentspace\n"
1672 " myhalf3 lightnormal;\n"
1673 " lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1674 " lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1675 " lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1676 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1677 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1678 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1679 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1680 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1681 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1682 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1683 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1684 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1685 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1686 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1687 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1689 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1690 " myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1691 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1697 "#ifdef MODE_FAKELIGHT\n"
1699 "myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
1700 "myhalf3 lightcolor = myhalf3(1.0);\n"
1701 "#endif // MODE_FAKELIGHT\n"
1706 "#ifdef MODE_LIGHTMAP\n"
1707 " color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1708 "#endif // MODE_LIGHTMAP\n"
1709 "#ifdef MODE_VERTEXCOLOR\n"
1710 " color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1711 "#endif // MODE_VERTEXCOLOR\n"
1712 "#ifdef MODE_FLATCOLOR\n"
1713 " color.rgb = diffusetex * Color_Ambient;\n"
1714 "#endif // MODE_FLATCOLOR\n"
1720 "# ifdef USEDIFFUSE\n"
1721 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1722 "# ifdef USESPECULAR\n"
1723 "# ifdef USEEXACTSPECULARMATH\n"
1724 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1726 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1727 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1729 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1731 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1734 " color.rgb = diffusetex * Color_Ambient;\n"
1738 "#ifdef USESHADOWMAPORTHO\n"
1739 " color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1742 "#ifdef USEDEFERREDLIGHTMAP\n"
1743 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1744 " color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1745 " color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1749 "#ifdef USEVERTEXTEXTUREBLEND\n"
1750 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1752 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1757 " color.rgb = FogVertex(color.rgb);\n"
1760 " // 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"
1761 "#ifdef USEREFLECTION\n"
1762 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1763 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1764 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1765 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1766 " // FIXME temporary hack to detect the case that the reflection\n"
1767 " // gets blackened at edges due to leaving the area that contains actual\n"
1769 " // Remove this 'ack once we have a better way to stop this thing from\n"
1771 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1772 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1773 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1774 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1775 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1776 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1779 " gl_FragColor = vec4(color);\n"
1781 "#endif // FRAGMENT_SHADER\n"
1783 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1784 "#endif // !MODE_DEFERREDGEOMETRY\n"
1785 "#endif // !MODE_WATER\n"
1786 "#endif // !MODE_REFRACTION\n"
1787 "#endif // !MODE_BLOOMBLUR\n"
1788 "#endif // !MODE_GENERIC\n"
1789 "#endif // !MODE_POSTPROCESS\n"
1790 "#endif // !MODE_SHOWDEPTH\n"
1791 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1795 =========================================================================================================================================================
1799 =========================================================================================================================================================
1803 =========================================================================================================================================================
1807 =========================================================================================================================================================
1811 =========================================================================================================================================================
1815 =========================================================================================================================================================
1819 =========================================================================================================================================================
1822 const char *builtincgshaderstring =
1823 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1824 "// written by Forest 'LordHavoc' Hale\n"
1825 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1827 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1828 "#if defined(USEREFLECTION)\n"
1829 "#undef USESHADOWMAPORTHO\n"
1832 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1835 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1836 "#define USELIGHTMAP\n"
1838 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
1839 "#define USEEYEVECTOR\n"
1842 "#ifdef FRAGMENT_SHADER\n"
1844 "//#undef USESHADOWMAPPCF\n"
1845 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1846 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1848 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1852 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1853 "#ifdef VERTEX_SHADER\n"
1856 "float4 gl_Vertex : POSITION,\n"
1857 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1858 "out float4 gl_Position : POSITION,\n"
1859 "out float Depth : TEXCOORD0\n"
1862 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1863 " Depth = gl_Position.z;\n"
1867 "#ifdef FRAGMENT_SHADER\n"
1870 "float Depth : TEXCOORD0,\n"
1871 "out float4 gl_FragColor : COLOR\n"
1874 "// float4 temp = float4(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0),0.0);\n"
1875 " float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
1876 " temp.yz -= floor(temp.yz);\n"
1877 " gl_FragColor = temp;\n"
1878 "// gl_FragColor = float4(Depth,0,0,0);\n"
1881 "#else // !MODE_DEPTH_ORSHADOW\n"
1886 "#ifdef MODE_SHOWDEPTH\n"
1887 "#ifdef VERTEX_SHADER\n"
1890 "float4 gl_Vertex : POSITION,\n"
1891 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1892 "out float4 gl_Position : POSITION,\n"
1893 "out float4 gl_FrontColor : COLOR0\n"
1896 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1897 " gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1901 "#ifdef FRAGMENT_SHADER\n"
1904 "float4 gl_FrontColor : COLOR0,\n"
1905 "out float4 gl_FragColor : COLOR\n"
1908 " gl_FragColor = gl_FrontColor;\n"
1911 "#else // !MODE_SHOWDEPTH\n"
1916 "#ifdef MODE_POSTPROCESS\n"
1918 "#ifdef VERTEX_SHADER\n"
1921 "float4 gl_Vertex : POSITION,\n"
1922 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1923 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1924 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1925 "out float4 gl_Position : POSITION,\n"
1926 "out float2 TexCoord1 : TEXCOORD0,\n"
1927 "out float2 TexCoord2 : TEXCOORD1\n"
1930 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1931 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
1933 " TexCoord2 = gl_MultiTexCoord4.xy;\n"
1938 "#ifdef FRAGMENT_SHADER\n"
1941 "float2 TexCoord1 : TEXCOORD0,\n"
1942 "float2 TexCoord2 : TEXCOORD1,\n"
1943 "uniform sampler Texture_First : register(s0),\n"
1945 "uniform sampler Texture_Second : register(s1),\n"
1947 "#ifdef USEGAMMARAMPS\n"
1948 "uniform sampler Texture_GammaRamps : register(s2),\n"
1950 "#ifdef USESATURATION\n"
1951 "uniform float Saturation : register(c30),\n"
1953 "#ifdef USEVIEWTINT\n"
1954 "uniform float4 ViewTintColor : register(c41),\n"
1956 "uniform float4 UserVec1 : register(c37),\n"
1957 "uniform float4 UserVec2 : register(c38),\n"
1958 "uniform float4 UserVec3 : register(c39),\n"
1959 "uniform float4 UserVec4 : register(c40),\n"
1960 "uniform float ClientTime : register(c2),\n"
1961 "uniform float2 PixelSize : register(c25),\n"
1962 "uniform float4 BloomColorSubtract : register(c43),\n"
1963 "out float4 gl_FragColor : COLOR\n"
1966 " gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1968 " gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
1970 "#ifdef USEVIEWTINT\n"
1971 " gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1974 "#ifdef USEPOSTPROCESSING\n"
1975 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1976 "// 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"
1977 " float sobel = 1.0;\n"
1978 " // float2 ts = textureSize(Texture_First, 0);\n"
1979 " // float2 px = float2(1/ts.x, 1/ts.y);\n"
1980 " float2 px = PixelSize;\n"
1981 " float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1982 " float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x, 0.0)).rgb;\n"
1983 " float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1984 " float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1985 " float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x, 0.0)).rgb;\n"
1986 " float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1987 " float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1988 " float3 y2 = tex2D(Texture_First, TexCoord1 + float2( 0.0,-px.y)).rgb;\n"
1989 " float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1990 " float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1991 " float3 y5 = tex2D(Texture_First, TexCoord1 + float2( 0.0, px.y)).rgb;\n"
1992 " float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1993 " float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
1994 " float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
1995 " float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
1996 " float px4 = 1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
1997 " float px5 = 2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
1998 " float px6 = 1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
1999 " float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
2000 " float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
2001 " float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
2002 " float py4 = 1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
2003 " float py5 = 2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
2004 " float py6 = 1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
2005 " sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
2006 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2007 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2008 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2009 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107, 0.707107)) * UserVec1.y;\n"
2010 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990, 0.891007)) * UserVec1.y;\n"
2011 " gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2012 " gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2015 "#ifdef USESATURATION\n"
2016 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2017 " float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2018 " // 'vampire sight' effect, wheres red is compensated\n"
2019 " #ifdef SATURATION_REDCOMPENSATE\n"
2020 " float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
2021 " gl_FragColor.rgb = mix(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2022 " gl_FragColor.r += r;\n"
2024 " // normal desaturation\n"
2025 " //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2026 " gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2030 "#ifdef USEGAMMARAMPS\n"
2031 " gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2032 " gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2033 " gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2037 "#else // !MODE_POSTPROCESS\n"
2042 "#ifdef MODE_GENERIC\n"
2043 "#ifdef VERTEX_SHADER\n"
2046 "float4 gl_Vertex : POSITION,\n"
2047 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2048 "float4 gl_Color : COLOR0,\n"
2049 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2050 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2051 "out float4 gl_Position : POSITION,\n"
2052 "#ifdef USEDIFFUSE\n"
2053 "out float2 TexCoord1 : TEXCOORD0,\n"
2055 "#ifdef USESPECULAR\n"
2056 "out float2 TexCoord2 : TEXCOORD1,\n"
2058 "out float4 gl_FrontColor : COLOR\n"
2062 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2064 " gl_FrontColor = gl_Color; // Cg is forward\n"
2066 "#ifdef USEDIFFUSE\n"
2067 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
2069 "#ifdef USESPECULAR\n"
2070 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
2072 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2076 "#ifdef FRAGMENT_SHADER\n"
2080 "float4 gl_FrontColor : COLOR0,\n"
2081 "float2 TexCoord1 : TEXCOORD0,\n"
2082 "float2 TexCoord2 : TEXCOORD1,\n"
2083 "#ifdef USEDIFFUSE\n"
2084 "uniform sampler Texture_First : register(s0),\n"
2086 "#ifdef USESPECULAR\n"
2087 "uniform sampler Texture_Second : register(s1),\n"
2089 "out float4 gl_FragColor : COLOR\n"
2092 " gl_FragColor = gl_FrontColor;\n"
2093 "#ifdef USEDIFFUSE\n"
2094 " gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2097 "#ifdef USESPECULAR\n"
2098 " float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2099 "# ifdef USECOLORMAPPING\n"
2100 " gl_FragColor *= tex2;\n"
2103 " gl_FragColor += tex2;\n"
2105 "# ifdef USEVERTEXTEXTUREBLEND\n"
2106 " gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2111 "#else // !MODE_GENERIC\n"
2116 "#ifdef MODE_BLOOMBLUR\n"
2117 "#ifdef VERTEX_SHADER\n"
2120 "float4 gl_Vertex : POSITION,\n"
2121 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2122 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2123 "out float4 gl_Position : POSITION,\n"
2124 "out float2 TexCoord : TEXCOORD0\n"
2127 " TexCoord = gl_MultiTexCoord0.xy;\n"
2128 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2132 "#ifdef FRAGMENT_SHADER\n"
2136 "float2 TexCoord : TEXCOORD0,\n"
2137 "uniform sampler Texture_First : register(s0),\n"
2138 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2139 "out float4 gl_FragColor : COLOR\n"
2143 " float2 tc = TexCoord;\n"
2144 " float3 color = tex2D(Texture_First, tc).rgb;\n"
2145 " tc += BloomBlur_Parameters.xy;\n"
2146 " for (i = 1;i < SAMPLES;i++)\n"
2148 " color += tex2D(Texture_First, tc).rgb;\n"
2149 " tc += BloomBlur_Parameters.xy;\n"
2151 " gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2154 "#else // !MODE_BLOOMBLUR\n"
2155 "#ifdef MODE_REFRACTION\n"
2156 "#ifdef VERTEX_SHADER\n"
2159 "float4 gl_Vertex : POSITION,\n"
2160 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2161 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2162 "uniform float4x4 TexMatrix : register(c0),\n"
2163 "uniform float3 EyePosition : register(c24),\n"
2164 "out float4 gl_Position : POSITION,\n"
2165 "out float2 TexCoord : TEXCOORD0,\n"
2166 "out float3 EyeVector : TEXCOORD1,\n"
2167 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2170 " TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2171 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2172 " ModelViewProjectionPosition = gl_Position;\n"
2176 "#ifdef FRAGMENT_SHADER\n"
2179 "float2 TexCoord : TEXCOORD0,\n"
2180 "float3 EyeVector : TEXCOORD1,\n"
2181 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2182 "uniform sampler Texture_Normal : register(s0),\n"
2183 "uniform sampler Texture_Refraction : register(s3),\n"
2184 "uniform sampler Texture_Reflection : register(s7),\n"
2185 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2186 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2187 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2188 "uniform float4 RefractColor : register(c29),\n"
2189 "out float4 gl_FragColor : COLOR\n"
2192 " float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2193 " //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"
2194 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2195 " float2 ScreenTexCoord = SafeScreenTexCoord + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy;\n"
2196 " // FIXME temporary hack to detect the case that the reflection\n"
2197 " // gets blackened at edges due to leaving the area that contains actual\n"
2199 " // Remove this 'ack once we have a better way to stop this thing from\n"
2201 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2202 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2203 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2204 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2205 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2206 " gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
2209 "#else // !MODE_REFRACTION\n"
2214 "#ifdef MODE_WATER\n"
2215 "#ifdef VERTEX_SHADER\n"
2219 "float4 gl_Vertex : POSITION,\n"
2220 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2221 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2222 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2223 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2224 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2225 "uniform float4x4 TexMatrix : register(c0),\n"
2226 "uniform float3 EyePosition : register(c24),\n"
2227 "out float4 gl_Position : POSITION,\n"
2228 "out float2 TexCoord : TEXCOORD0,\n"
2229 "out float3 EyeVector : TEXCOORD1,\n"
2230 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2233 " TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2234 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2235 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2236 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2237 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2238 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2239 " ModelViewProjectionPosition = gl_Position;\n"
2243 "#ifdef FRAGMENT_SHADER\n"
2246 "float2 TexCoord : TEXCOORD0,\n"
2247 "float3 EyeVector : TEXCOORD1,\n"
2248 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2249 "uniform sampler Texture_Normal : register(s0),\n"
2250 "uniform sampler Texture_Refraction : register(s3),\n"
2251 "uniform sampler Texture_Reflection : register(s7),\n"
2252 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2253 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2254 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2255 "uniform float4 RefractColor : register(c29),\n"
2256 "uniform float4 ReflectColor : register(c26),\n"
2257 "uniform float ReflectFactor : register(c27),\n"
2258 "uniform float ReflectOffset : register(c28),\n"
2259 "out float4 gl_FragColor : COLOR\n"
2262 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2263 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2264 " float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2265 " //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2266 " float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2267 " // FIXME temporary hack to detect the case that the reflection\n"
2268 " // gets blackened at edges due to leaving the area that contains actual\n"
2270 " // Remove this 'ack once we have a better way to stop this thing from\n"
2272 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2273 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2274 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2275 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2276 " ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2277 " f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2278 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2279 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2280 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2281 " ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2282 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2283 " gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
2286 "#else // !MODE_WATER\n"
2291 "// 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"
2293 "// fragment shader specific:\n"
2294 "#ifdef FRAGMENT_SHADER\n"
2297 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2300 "#ifdef USEFOGHEIGHTTEXTURE\n"
2301 " float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2302 " fogfrac = fogheightpixel.a;\n"
2303 " return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2305 "# ifdef USEFOGOUTSIDE\n"
2306 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2308 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2310 " return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2315 "#ifdef USEOFFSETMAPPING\n"
2316 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2318 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2319 " // 14 sample relief mapping: linear search and then binary search\n"
2320 " // this basically steps forward a small amount repeatedly until it finds\n"
2321 " // itself inside solid, then jitters forward and back using decreasing\n"
2322 " // amounts to find the impact\n"
2323 " //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2324 " //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2325 " float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2326 " float3 RT = float3(TexCoord, 1);\n"
2327 " OffsetVector *= 0.1;\n"
2328 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2329 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2330 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2331 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2332 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2333 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2334 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2335 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2336 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2337 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
2338 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
2339 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
2340 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
2341 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2344 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2345 " // this basically moves forward the full distance, and then backs up based\n"
2346 " // on height of samples\n"
2347 " //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2348 " //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2349 " float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2350 " TexCoord += OffsetVector;\n"
2351 " OffsetVector *= 0.333;\n"
2352 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2353 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2354 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2355 " return TexCoord;\n"
2358 "#endif // USEOFFSETMAPPING\n"
2360 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2361 "#if defined(USESHADOWMAP2D)\n"
2362 "# ifdef USESHADOWMAPORTHO\n"
2363 "# define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2365 "# ifdef USESHADOWMAPVSDCT\n"
2366 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2368 " float3 adir = abs(dir);\n"
2369 " float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2370 " float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2371 " return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2374 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2376 " float3 adir = abs(dir);\n"
2377 " float ma = adir.z;\n"
2378 " float4 proj = float4(dir, 2.5);\n"
2379 " if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2380 " if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2382 " 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"
2384 " float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2385 " 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"
2390 "#endif // defined(USESHADOWMAP2D)\n"
2392 "# ifdef USESHADOWMAP2D\n"
2393 "#ifdef USESHADOWMAPVSDCT\n"
2394 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2396 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2399 "#ifdef USESHADOWMAPVSDCT\n"
2400 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2402 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2406 "# ifdef USESHADOWSAMPLER\n"
2407 "# ifdef USESHADOWMAPPCF\n"
2408 "# define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r \n"
2409 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2410 " 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"
2412 " f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2415 "# ifdef USESHADOWMAPPCF\n"
2416 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2417 "# ifdef GL_ARB_texture_gather\n"
2418 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2420 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2422 " float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2423 "# if USESHADOWMAPPCF > 1\n"
2424 " float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2425 " float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2426 " float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2427 " float4 group4 = step(shadowmaptc.z, texval(-2.0, 0.0));\n"
2428 " float4 group5 = step(shadowmaptc.z, texval( 0.0, 0.0));\n"
2429 " float4 group6 = step(shadowmaptc.z, texval( 2.0, 0.0));\n"
2430 " float4 group7 = step(shadowmaptc.z, texval(-2.0, 2.0));\n"
2431 " float4 group8 = step(shadowmaptc.z, texval( 0.0, 2.0));\n"
2432 " float4 group9 = step(shadowmaptc.z, texval( 2.0, 2.0));\n"
2433 " float4 locols = float4(group1.ab, group3.ab);\n"
2434 " float4 hicols = float4(group7.rg, group9.rg);\n"
2435 " locols.yz += group2.ab;\n"
2436 " hicols.yz += group8.rg;\n"
2437 " float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2438 " float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2439 " lerp(locols, hicols, offset.y);\n"
2440 " float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2441 " cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2442 " f = dot(cols, float4(1.0/25.0));\n"
2444 " float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2445 " float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2446 " float4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
2447 " float4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
2448 " float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2449 " lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2450 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2453 "# ifdef GL_EXT_gpu_shader4\n"
2454 "# define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2456 "# define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r \n"
2458 "# if USESHADOWMAPPCF > 1\n"
2459 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2460 " center *= ShadowMap_TextureScale;\n"
2461 " 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"
2462 " 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"
2463 " 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"
2464 " 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"
2465 " float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2466 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2468 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2469 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2470 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2471 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2472 " float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2473 " f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2477 " f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2480 "# ifdef USESHADOWMAPORTHO\n"
2481 " return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2487 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2488 "#endif // FRAGMENT_SHADER\n"
2493 "#ifdef MODE_DEFERREDGEOMETRY\n"
2494 "#ifdef VERTEX_SHADER\n"
2497 "float4 gl_Vertex : POSITION,\n"
2498 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2499 "#ifdef USEVERTEXTEXTUREBLEND\n"
2500 "float4 gl_Color : COLOR0,\n"
2502 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2503 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2504 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2505 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2506 "uniform float4x4 TexMatrix : register(c0),\n"
2507 "#ifdef USEVERTEXTEXTUREBLEND\n"
2508 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2510 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2511 "#ifdef USEOFFSETMAPPING\n"
2512 "uniform float3 EyePosition : register(c24),\n"
2514 "out float4 gl_Position : POSITION,\n"
2515 "#ifdef USEVERTEXTEXTUREBLEND\n"
2516 "out float4 gl_FrontColor : COLOR,\n"
2518 "out float4 TexCoordBoth : TEXCOORD0,\n"
2519 "#ifdef USEOFFSETMAPPING\n"
2520 "out float3 EyeVector : TEXCOORD2,\n"
2522 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2523 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2524 "out float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\n"
2527 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2528 "#ifdef USEVERTEXTEXTUREBLEND\n"
2530 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2532 " gl_FrontColor = gl_Color; // Cg is forward\n"
2534 " TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2537 " // transform unnormalized eye direction into tangent space\n"
2538 "#ifdef USEOFFSETMAPPING\n"
2539 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2540 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2541 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2542 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2545 " VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2546 " VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2547 " VectorR.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2548 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2549 " VectorR.w = gl_Position.z;\n"
2551 "#endif // VERTEX_SHADER\n"
2553 "#ifdef FRAGMENT_SHADER\n"
2556 "float4 TexCoordBoth : TEXCOORD0,\n"
2557 "float3 EyeVector : TEXCOORD2,\n"
2558 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2559 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2560 "float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
2561 "uniform sampler Texture_Normal : register(s0),\n"
2562 "#ifdef USEALPHAKILL\n"
2563 "uniform sampler Texture_Color : register(s1),\n"
2565 "uniform sampler Texture_Gloss : register(s2),\n"
2566 "#ifdef USEVERTEXTEXTUREBLEND\n"
2567 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2568 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2570 "#ifdef USEOFFSETMAPPING\n"
2571 "uniform float OffsetMapping_Scale : register(c24),\n"
2573 "uniform half SpecularPower : register(c36),\n"
2575 "out float4 gl_FragData0 : COLOR0,\n"
2576 "out float4 gl_FragData1 : COLOR1\n"
2578 "out float4 gl_FragColor : COLOR\n"
2582 " float2 TexCoord = TexCoordBoth.xy;\n"
2583 "#ifdef USEOFFSETMAPPING\n"
2584 " // apply offsetmapping\n"
2585 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2586 "#define TexCoord TexCoordOffset\n"
2589 "#ifdef USEALPHAKILL\n"
2590 " if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2594 "#ifdef USEVERTEXTEXTUREBLEND\n"
2595 " float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2596 " float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2597 " //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2598 " //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2601 "#ifdef USEVERTEXTEXTUREBLEND\n"
2602 " float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2603 " float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2605 " float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2606 " float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2610 " 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"
2611 " float Depth = VectorR.w / 256.0;\n"
2612 " float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
2613 "// float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
2614 " depthcolor.yz -= floor(depthcolor.yz);\n"
2615 " gl_FragData1 = depthcolor;\n"
2617 " gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2620 "#endif // FRAGMENT_SHADER\n"
2621 "#else // !MODE_DEFERREDGEOMETRY\n"
2626 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2627 "#ifdef VERTEX_SHADER\n"
2630 "float4 gl_Vertex : POSITION,\n"
2631 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2632 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2633 "out float4 gl_Position : POSITION,\n"
2634 "out float4 ModelViewPosition : TEXCOORD0\n"
2637 " ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2638 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2640 "#endif // VERTEX_SHADER\n"
2642 "#ifdef FRAGMENT_SHADER\n"
2646 "float2 Pixel : VPOS,\n"
2648 "float2 Pixel : WPOS,\n"
2650 "float4 ModelViewPosition : TEXCOORD0,\n"
2651 "uniform float4x4 ViewToLight : register(c44),\n"
2652 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2653 "uniform float3 LightPosition : register(c23),\n"
2654 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2655 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2656 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2657 "#ifdef USESPECULAR\n"
2658 "uniform half3 DeferredColor_Specular : register(c11),\n"
2659 "uniform half SpecularPower : register(c36),\n"
2661 "uniform sampler Texture_Attenuation : register(s9),\n"
2662 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2663 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2665 "#ifdef USECUBEFILTER\n"
2666 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2669 "#ifdef USESHADOWMAP2D\n"
2670 "# ifdef USESHADOWSAMPLER\n"
2671 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2673 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2677 "#ifdef USESHADOWMAPVSDCT\n"
2678 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2681 "#if defined(USESHADOWMAP2D)\n"
2682 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2683 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2686 "out float4 gl_FragData0 : COLOR0,\n"
2687 "out float4 gl_FragData1 : COLOR1\n"
2690 " // calculate viewspace pixel position\n"
2691 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2692 " //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2693 " float3 position;\n"
2695 " position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
2697 " position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2699 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2700 " // decode viewspace pixel normal\n"
2701 " half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2702 " half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2703 " // surfacenormal = pixel normal in viewspace\n"
2704 " // LightVector = pixel to light in viewspace\n"
2705 " // CubeVector = position in lightspace\n"
2706 " // eyevector = pixel to view in viewspace\n"
2707 " float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2708 " half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2709 "#ifdef USEDIFFUSE\n"
2710 " // calculate diffuse shading\n"
2711 " half3 lightnormal = half3(normalize(LightPosition - position));\n"
2712 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2714 "#ifdef USESPECULAR\n"
2715 " // calculate directional shading\n"
2716 " float3 eyevector = position * -1.0;\n"
2717 "# ifdef USEEXACTSPECULARMATH\n"
2718 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
2720 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2721 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
2725 "#if defined(USESHADOWMAP2D)\n"
2726 " fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2727 "#ifdef USESHADOWMAPVSDCT\n"
2728 ", Texture_CubeProjection\n"
2733 "#ifdef USEDIFFUSE\n"
2734 " gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2736 " gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2738 "#ifdef USESPECULAR\n"
2739 " gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2741 " gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2744 "# ifdef USECUBEFILTER\n"
2745 " float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2746 " gl_FragData0.rgb *= cubecolor;\n"
2747 " gl_FragData1.rgb *= cubecolor;\n"
2750 "#endif // FRAGMENT_SHADER\n"
2751 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2756 "#ifdef VERTEX_SHADER\n"
2759 "float4 gl_Vertex : POSITION,\n"
2760 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2761 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2762 "float4 gl_Color : COLOR0,\n"
2764 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2765 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2766 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2767 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2768 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2770 "uniform float3 EyePosition : register(c24),\n"
2771 "uniform float4x4 TexMatrix : register(c0),\n"
2772 "#ifdef USEVERTEXTEXTUREBLEND\n"
2773 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2775 "#ifdef MODE_LIGHTSOURCE\n"
2776 "uniform float4x4 ModelToLight : register(c20),\n"
2778 "#ifdef MODE_LIGHTSOURCE\n"
2779 "uniform float3 LightPosition : register(c27),\n"
2781 "#ifdef MODE_LIGHTDIRECTION\n"
2782 "uniform float3 LightDir : register(c26),\n"
2784 "uniform float4 FogPlane : register(c25),\n"
2785 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2786 "uniform float3 LightPosition : register(c27),\n"
2788 "#ifdef USESHADOWMAPORTHO\n"
2789 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2791 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2792 "out float4 gl_FrontColor : COLOR,\n"
2794 "out float4 TexCoordBoth : TEXCOORD0,\n"
2795 "#ifdef USELIGHTMAP\n"
2796 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2798 "#ifdef USEEYEVECTOR\n"
2799 "out float3 EyeVector : TEXCOORD2,\n"
2801 "#ifdef USEREFLECTION\n"
2802 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2805 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2807 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE) || defined(USEDIFFUSE)\n"
2808 "out float3 LightVector : TEXCOORD1,\n"
2810 "#ifdef MODE_LIGHTSOURCE\n"
2811 "out float3 CubeVector : TEXCOORD3,\n"
2813 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2814 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2815 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2816 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2818 "#ifdef USESHADOWMAPORTHO\n"
2819 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2821 "out float4 gl_Position : POSITION\n"
2824 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2826 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2828 " gl_FrontColor = gl_Color; // Cg is forward\n"
2831 " // copy the surface texcoord\n"
2832 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2833 "#ifdef USEVERTEXTEXTUREBLEND\n"
2834 " TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2836 "#ifdef USELIGHTMAP\n"
2837 " TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2840 "#ifdef MODE_LIGHTSOURCE\n"
2841 " // transform vertex position into light attenuation/cubemap space\n"
2842 " // (-1 to +1 across the light box)\n"
2843 " CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2845 "# ifdef USEDIFFUSE\n"
2846 " // transform unnormalized light direction into tangent space\n"
2847 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
2848 " // normalize it per pixel)\n"
2849 " float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2850 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2851 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2852 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2856 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2857 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2858 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2859 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2862 " // transform unnormalized eye direction into tangent space\n"
2863 "#ifdef USEEYEVECTOR\n"
2864 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2865 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2866 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2867 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2871 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2872 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2875 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2876 " VectorS = gl_MultiTexCoord1.xyz;\n"
2877 " VectorT = gl_MultiTexCoord2.xyz;\n"
2878 " VectorR = gl_MultiTexCoord3.xyz;\n"
2881 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2882 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2884 "#ifdef USESHADOWMAPORTHO\n"
2885 " ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2888 "#ifdef USEREFLECTION\n"
2889 " ModelViewProjectionPosition = gl_Position;\n"
2892 "#endif // VERTEX_SHADER\n"
2897 "#ifdef FRAGMENT_SHADER\n"
2900 "#ifdef USEDEFERREDLIGHTMAP\n"
2902 "float2 Pixel : VPOS,\n"
2904 "float2 Pixel : WPOS,\n"
2907 "float4 gl_FrontColor : COLOR,\n"
2908 "float4 TexCoordBoth : TEXCOORD0,\n"
2909 "#ifdef USELIGHTMAP\n"
2910 "float2 TexCoordLightmap : TEXCOORD1,\n"
2912 "#ifdef USEEYEVECTOR\n"
2913 "float3 EyeVector : TEXCOORD2,\n"
2915 "#ifdef USEREFLECTION\n"
2916 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2919 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2921 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2922 "float3 LightVector : TEXCOORD1,\n"
2924 "#ifdef MODE_LIGHTSOURCE\n"
2925 "float3 CubeVector : TEXCOORD3,\n"
2927 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2928 "float4 ModelViewPosition : TEXCOORD0,\n"
2930 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2931 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2932 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2933 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2935 "#ifdef USESHADOWMAPORTHO\n"
2936 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2939 "uniform sampler Texture_Normal : register(s0),\n"
2940 "uniform sampler Texture_Color : register(s1),\n"
2941 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2942 "uniform sampler Texture_Gloss : register(s2),\n"
2945 "uniform sampler Texture_Glow : register(s3),\n"
2947 "#ifdef USEVERTEXTEXTUREBLEND\n"
2948 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2949 "uniform sampler Texture_SecondaryColor : register(s5),\n"
2950 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2951 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2954 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
2957 "#ifdef USECOLORMAPPING\n"
2958 "uniform sampler Texture_Pants : register(s4),\n"
2959 "uniform sampler Texture_Shirt : register(s7),\n"
2962 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
2963 "uniform sampler Texture_FogMask : register(s8),\n"
2965 "#ifdef USELIGHTMAP\n"
2966 "uniform sampler Texture_Lightmap : register(s9),\n"
2968 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2969 "uniform sampler Texture_Deluxemap : register(s10),\n"
2971 "#ifdef USEREFLECTION\n"
2972 "uniform sampler Texture_Reflection : register(s7),\n"
2975 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2976 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2977 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2979 "#ifdef USEDEFERREDLIGHTMAP\n"
2980 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2981 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2982 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
2983 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
2986 "#ifdef USECOLORMAPPING\n"
2987 "uniform half3 Color_Pants : register(c7),\n"
2988 "uniform half3 Color_Shirt : register(c8),\n"
2991 "uniform float3 FogColor : register(c16),\n"
2992 "uniform float FogRangeRecip : register(c20),\n"
2993 "uniform float FogPlaneViewDist : register(c19),\n"
2994 "uniform float FogHeightFade : register(c17),\n"
2997 "#ifdef USEOFFSETMAPPING\n"
2998 "uniform float OffsetMapping_Scale : register(c24),\n"
3001 "#ifdef USEDEFERREDLIGHTMAP\n"
3002 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
3003 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
3004 "uniform half3 DeferredMod_Specular : register(c13),\n"
3006 "uniform half3 Color_Ambient : register(c3),\n"
3007 "uniform half3 Color_Diffuse : register(c4),\n"
3008 "uniform half3 Color_Specular : register(c5),\n"
3009 "uniform half SpecularPower : register(c36),\n"
3011 "uniform half3 Color_Glow : register(c6),\n"
3013 "uniform half Alpha : register(c0),\n"
3014 "#ifdef USEREFLECTION\n"
3015 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3016 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3017 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3018 "uniform half4 ReflectColor : register(c26),\n"
3020 "#ifdef USEREFLECTCUBE\n"
3021 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3022 "uniform sampler Texture_ReflectMask : register(s5),\n"
3023 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3025 "#ifdef MODE_LIGHTDIRECTION\n"
3026 "uniform half3 LightColor : register(c21),\n"
3028 "#ifdef MODE_LIGHTSOURCE\n"
3029 "uniform half3 LightColor : register(c21),\n"
3032 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3033 "uniform sampler Texture_Attenuation : register(s9),\n"
3034 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3037 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3039 "#ifdef USESHADOWMAP2D\n"
3040 "# ifdef USESHADOWSAMPLER\n"
3041 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3043 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3047 "#ifdef USESHADOWMAPVSDCT\n"
3048 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3051 "#if defined(USESHADOWMAP2D)\n"
3052 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3053 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3055 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3057 "out float4 gl_FragColor : COLOR\n"
3060 " float2 TexCoord = TexCoordBoth.xy;\n"
3061 "#ifdef USEVERTEXTEXTUREBLEND\n"
3062 " float2 TexCoord2 = TexCoordBoth.zw;\n"
3064 "#ifdef USEOFFSETMAPPING\n"
3065 " // apply offsetmapping\n"
3066 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3067 "#define TexCoord TexCoordOffset\n"
3070 " // combine the diffuse textures (base, pants, shirt)\n"
3071 " half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3072 "#ifdef USEALPHAKILL\n"
3073 " if (color.a < 0.5)\n"
3076 " color.a *= Alpha;\n"
3077 "#ifdef USECOLORMAPPING\n"
3078 " color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3080 "#ifdef USEVERTEXTEXTUREBLEND\n"
3081 " half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3082 " //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3083 " //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3084 " color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3086 " //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3089 " // get the surface normal\n"
3090 "#ifdef USEVERTEXTEXTUREBLEND\n"
3091 " half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3093 " half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3096 " // get the material colors\n"
3097 " half3 diffusetex = color.rgb;\n"
3098 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3099 "# ifdef USEVERTEXTEXTUREBLEND\n"
3100 " half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3102 " half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3106 "#ifdef USEREFLECTCUBE\n"
3107 " float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3108 " float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3109 " float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3110 " diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3116 "#ifdef MODE_LIGHTSOURCE\n"
3117 " // light source\n"
3118 "#ifdef USEDIFFUSE\n"
3119 " half3 lightnormal = half3(normalize(LightVector));\n"
3120 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3121 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3122 "#ifdef USESPECULAR\n"
3123 "#ifdef USEEXACTSPECULARMATH\n"
3124 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3126 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3127 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3129 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3132 " color.rgb = diffusetex * Color_Ambient;\n"
3134 " color.rgb *= LightColor;\n"
3135 " color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3136 "#if defined(USESHADOWMAP2D)\n"
3137 " color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3138 "#ifdef USESHADOWMAPVSDCT\n"
3139 ", Texture_CubeProjection\n"
3144 "# ifdef USECUBEFILTER\n"
3145 " color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3148 "#ifdef USESHADOWMAP2D\n"
3149 "#ifdef USESHADOWMAPVSDCT\n"
3150 "// float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3152 "// float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3154 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3155 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3156 "// color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3157 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3158 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3159 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3160 "// color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3161 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3162 "// color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3163 "// color.r = half(shadowmaptc.z);\n"
3164 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3165 "// color.r = half(shadowmaptc.z);\n"
3167 "// color.rgb = abs(CubeVector);\n"
3169 "// color.rgb = half3(1,1,1);\n"
3170 "#endif // MODE_LIGHTSOURCE\n"
3175 "#ifdef MODE_LIGHTDIRECTION\n"
3177 "#ifdef USEDIFFUSE\n"
3178 " half3 lightnormal = half3(normalize(LightVector));\n"
3180 "#define lightcolor LightColor\n"
3181 "#endif // MODE_LIGHTDIRECTION\n"
3182 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3184 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3185 " half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3186 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3187 " // convert modelspace light vector to tangentspace\n"
3188 " half3 lightnormal;\n"
3189 " lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3190 " lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3191 " lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3192 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3193 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3194 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3195 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3196 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3197 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3198 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3199 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3200 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3201 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3202 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3203 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3205 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3206 " half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3207 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3213 "#ifdef MODE_FAKELIGHT\n"
3215 "half3 lightnormal = half3(normalize(EyeVector));\n"
3216 "half3 lightcolor = half3(1.0,1.0,1.0);\n"
3217 "#endif // MODE_FAKELIGHT\n"
3222 "#ifdef MODE_LIGHTMAP\n"
3223 " color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3224 "#endif // MODE_LIGHTMAP\n"
3225 "#ifdef MODE_VERTEXCOLOR\n"
3226 " color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3227 "#endif // MODE_VERTEXCOLOR\n"
3228 "#ifdef MODE_FLATCOLOR\n"
3229 " color.rgb = diffusetex * Color_Ambient;\n"
3230 "#endif // MODE_FLATCOLOR\n"
3236 "# ifdef USEDIFFUSE\n"
3237 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3238 "# ifdef USESPECULAR\n"
3239 "# ifdef USEEXACTSPECULARMATH\n"
3240 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3242 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3243 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3245 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3247 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3250 " color.rgb = diffusetex * Color_Ambient;\n"
3254 "#ifdef USESHADOWMAPORTHO\n"
3255 " color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
3258 "#ifdef USEDEFERREDLIGHTMAP\n"
3259 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3260 " color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3261 " color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3262 "// color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
3263 "// color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
3267 "#ifdef USEVERTEXTEXTUREBLEND\n"
3268 " color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3270 " color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3275 " color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3278 " // 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"
3279 "#ifdef USEREFLECTION\n"
3280 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3281 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3282 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3283 " float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3284 " // FIXME temporary hack to detect the case that the reflection\n"
3285 " // gets blackened at edges due to leaving the area that contains actual\n"
3287 " // Remove this 'ack once we have a better way to stop this thing from\n"
3289 " float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3290 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3291 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3292 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3293 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3294 " color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3297 " gl_FragColor = float4(color);\n"
3299 "#endif // FRAGMENT_SHADER\n"
3301 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3302 "#endif // !MODE_DEFERREDGEOMETRY\n"
3303 "#endif // !MODE_WATER\n"
3304 "#endif // !MODE_REFRACTION\n"
3305 "#endif // !MODE_BLOOMBLUR\n"
3306 "#endif // !MODE_GENERIC\n"
3307 "#endif // !MODE_POSTPROCESS\n"
3308 "#endif // !MODE_SHOWDEPTH\n"
3309 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3312 char *glslshaderstring = NULL;
3313 char *cgshaderstring = NULL;
3314 char *hlslshaderstring = NULL;
3316 //=======================================================================================================================================================
3318 typedef struct shaderpermutationinfo_s
3320 const char *pretext;
3323 shaderpermutationinfo_t;
3325 typedef struct shadermodeinfo_s
3327 const char *vertexfilename;
3328 const char *geometryfilename;
3329 const char *fragmentfilename;
3330 const char *pretext;
3335 typedef enum shaderpermutation_e
3337 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3338 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3339 SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3340 SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3341 SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3342 SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3343 SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3344 SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3345 SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3346 SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3347 SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3348 SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3349 SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3350 SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3351 SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3352 SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3353 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3354 SHADERPERMUTATION_SHADOWMAP2D = 1<<17, ///< (lightsource) use shadowmap texture as light filter
3355 SHADERPERMUTATION_SHADOWMAPPCF = 1<<18, ///< (lightsource) use percentage closer filtering on shadowmap test results
3356 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<19, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3357 SHADERPERMUTATION_SHADOWSAMPLER = 1<<20, ///< (lightsource) use hardware shadowmap test
3358 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<21, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3359 SHADERPERMUTATION_SHADOWMAPORTHO = 1<<22, //< (lightsource) use orthographic shadowmap projection
3360 SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<23, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3361 SHADERPERMUTATION_ALPHAKILL = 1<<24, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3362 SHADERPERMUTATION_REFLECTCUBE = 1<<25, ///< fake reflections using global cubemap (not HDRI light probe)
3363 SHADERPERMUTATION_NORMALMAPSCROLLBLEND = 1<<26, // (water) counter-direction normalmaps scrolling
3364 SHADERPERMUTATION_LIMIT = 1<<27, ///< size of permutations array
3365 SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
3367 shaderpermutation_t;
3369 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3370 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3372 {"#define USEDIFFUSE\n", " diffuse"},
3373 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3374 {"#define USEVIEWTINT\n", " viewtint"},
3375 {"#define USECOLORMAPPING\n", " colormapping"},
3376 {"#define USESATURATION\n", " saturation"},
3377 {"#define USEFOGINSIDE\n", " foginside"},
3378 {"#define USEFOGOUTSIDE\n", " fogoutside"},
3379 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3380 {"#define USEGAMMARAMPS\n", " gammaramps"},
3381 {"#define USECUBEFILTER\n", " cubefilter"},
3382 {"#define USEGLOW\n", " glow"},
3383 {"#define USEBLOOM\n", " bloom"},
3384 {"#define USESPECULAR\n", " specular"},
3385 {"#define USEPOSTPROCESSING\n", " postprocessing"},
3386 {"#define USEREFLECTION\n", " reflection"},
3387 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3388 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3389 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3390 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3391 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3392 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3393 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3394 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3395 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3396 {"#define USEALPHAKILL\n", " alphakill"},
3397 {"#define USEREFLECTCUBE\n", " reflectcube"},
3398 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
3401 // this enum selects which of the glslshadermodeinfo entries should be used
3402 typedef enum shadermode_e
3404 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3405 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3406 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3407 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3408 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3409 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3410 SHADERMODE_FAKELIGHT, ///< (fakelight) modulate texture by "fake" lighting (no lightmaps, no nothing)
3411 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3412 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3413 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3414 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3415 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3416 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3417 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3418 SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3419 SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3424 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3425 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3427 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3428 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3429 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3430 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3431 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3432 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3433 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3434 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3435 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3436 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3437 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3438 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3439 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3440 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3441 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3442 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3446 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3448 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3449 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3450 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3451 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3452 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3453 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3454 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FAKELIGHT\n", " fakelight"},
3455 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3456 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3457 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3458 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3459 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3460 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3461 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3462 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3463 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3468 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3470 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3471 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3472 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3473 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3474 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3475 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3476 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3477 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3478 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3479 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3480 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3481 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3482 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3483 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3484 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3485 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3489 struct r_glsl_permutation_s;
3490 typedef struct r_glsl_permutation_s
3492 /// hash lookup data
3493 struct r_glsl_permutation_s *hashnext;
3495 unsigned int permutation;
3497 /// indicates if we have tried compiling this permutation already
3499 /// 0 if compilation failed
3501 /// locations of detected uniforms in program object, or -1 if not found
3502 int loc_Texture_First;
3503 int loc_Texture_Second;
3504 int loc_Texture_GammaRamps;
3505 int loc_Texture_Normal;
3506 int loc_Texture_Color;
3507 int loc_Texture_Gloss;
3508 int loc_Texture_Glow;
3509 int loc_Texture_SecondaryNormal;
3510 int loc_Texture_SecondaryColor;
3511 int loc_Texture_SecondaryGloss;
3512 int loc_Texture_SecondaryGlow;
3513 int loc_Texture_Pants;
3514 int loc_Texture_Shirt;
3515 int loc_Texture_FogHeightTexture;
3516 int loc_Texture_FogMask;
3517 int loc_Texture_Lightmap;
3518 int loc_Texture_Deluxemap;
3519 int loc_Texture_Attenuation;
3520 int loc_Texture_Cube;
3521 int loc_Texture_Refraction;
3522 int loc_Texture_Reflection;
3523 int loc_Texture_ShadowMap2D;
3524 int loc_Texture_CubeProjection;
3525 int loc_Texture_ScreenDepth;
3526 int loc_Texture_ScreenNormalMap;
3527 int loc_Texture_ScreenDiffuse;
3528 int loc_Texture_ScreenSpecular;
3529 int loc_Texture_ReflectMask;
3530 int loc_Texture_ReflectCube;
3532 int loc_BloomBlur_Parameters;
3534 int loc_Color_Ambient;
3535 int loc_Color_Diffuse;
3536 int loc_Color_Specular;
3538 int loc_Color_Pants;
3539 int loc_Color_Shirt;
3540 int loc_DeferredColor_Ambient;
3541 int loc_DeferredColor_Diffuse;
3542 int loc_DeferredColor_Specular;
3543 int loc_DeferredMod_Diffuse;
3544 int loc_DeferredMod_Specular;
3545 int loc_DistortScaleRefractReflect;
3546 int loc_EyePosition;
3548 int loc_FogHeightFade;
3550 int loc_FogPlaneViewDist;
3551 int loc_FogRangeRecip;
3554 int loc_LightPosition;
3555 int loc_OffsetMapping_Scale;
3557 int loc_ReflectColor;
3558 int loc_ReflectFactor;
3559 int loc_ReflectOffset;
3560 int loc_RefractColor;
3562 int loc_ScreenCenterRefractReflect;
3563 int loc_ScreenScaleRefractReflect;
3564 int loc_ScreenToDepth;
3565 int loc_ShadowMap_Parameters;
3566 int loc_ShadowMap_TextureScale;
3567 int loc_SpecularPower;
3572 int loc_ViewTintColor;
3573 int loc_ViewToLight;
3574 int loc_ModelToLight;
3576 int loc_BackgroundTexMatrix;
3577 int loc_ModelViewProjectionMatrix;
3578 int loc_ModelViewMatrix;
3579 int loc_PixelToScreenTexCoord;
3580 int loc_ModelToReflectCube;
3581 int loc_ShadowMapMatrix;
3582 int loc_BloomColorSubtract;
3583 int loc_NormalmapScrollBlend;
3585 r_glsl_permutation_t;
3587 #define SHADERPERMUTATION_HASHSIZE 256
3590 // non-degradable "lightweight" shader parameters to keep the permutations simpler
3591 // these can NOT degrade! only use for simple stuff
3594 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
3595 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3596 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
3597 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
3598 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
3599 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5 ///< postprocess uservec4 is enabled
3601 #define SHADERSTATICPARMS_COUNT 6
3603 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
3604 static int shaderstaticparms_count = 0;
3606 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
3607 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
3608 qboolean R_CompileShader_CheckStaticParms(void)
3610 static int r_compileshader_staticparms_save[1];
3611 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
3612 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
3615 if (r_glsl_saturation_redcompensate.integer)
3616 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
3617 if (r_shadow_glossexact.integer)
3618 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
3619 if (r_glsl_postprocess.integer)
3621 if (r_glsl_postprocess_uservec1_enable.integer)
3622 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
3623 if (r_glsl_postprocess_uservec2_enable.integer)
3624 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
3625 if (r_glsl_postprocess_uservec3_enable.integer)
3626 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
3627 if (r_glsl_postprocess_uservec4_enable.integer)
3628 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
3630 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
3633 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
3634 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
3635 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
3637 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
3638 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
3640 shaderstaticparms_count = 0;
3643 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
3644 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
3645 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
3646 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
3647 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
3648 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
3651 /// information about each possible shader permutation
3652 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3653 /// currently selected permutation
3654 r_glsl_permutation_t *r_glsl_permutation;
3655 /// storage for permutations linked in the hash table
3656 memexpandablearray_t r_glsl_permutationarray;
3658 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3660 //unsigned int hashdepth = 0;
3661 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3662 r_glsl_permutation_t *p;
3663 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3665 if (p->mode == mode && p->permutation == permutation)
3667 //if (hashdepth > 10)
3668 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3673 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3675 p->permutation = permutation;
3676 p->hashnext = r_glsl_permutationhash[mode][hashindex];
3677 r_glsl_permutationhash[mode][hashindex] = p;
3678 //if (hashdepth > 10)
3679 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3683 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3686 if (!filename || !filename[0])
3688 if (!strcmp(filename, "glsl/default.glsl"))
3690 if (!glslshaderstring)
3692 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3693 if (glslshaderstring)
3694 Con_DPrintf("Loading shaders from file %s...\n", filename);
3696 glslshaderstring = (char *)builtinshaderstring;
3698 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3699 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3700 return shaderstring;
3702 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3705 if (printfromdisknotice)
3706 Con_DPrintf("from disk %s... ", filename);
3707 return shaderstring;
3709 return shaderstring;
3712 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3715 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3716 char *vertexstring, *geometrystring, *fragmentstring;
3717 char permutationname[256];
3718 int vertstrings_count = 0;
3719 int geomstrings_count = 0;
3720 int fragstrings_count = 0;
3721 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3722 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3723 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3730 permutationname[0] = 0;
3731 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
3732 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3733 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3735 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3737 // the first pretext is which type of shader to compile as
3738 // (later these will all be bound together as a program object)
3739 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3740 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3741 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3743 // the second pretext is the mode (for example a light source)
3744 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3745 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3746 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3747 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3749 // now add all the permutation pretexts
3750 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3752 if (permutation & (1<<i))
3754 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3755 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3756 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3757 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3761 // keep line numbers correct
3762 vertstrings_list[vertstrings_count++] = "\n";
3763 geomstrings_list[geomstrings_count++] = "\n";
3764 fragstrings_list[fragstrings_count++] = "\n";
3769 R_CompileShader_AddStaticParms(mode, permutation);
3770 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3771 vertstrings_count += shaderstaticparms_count;
3772 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3773 geomstrings_count += shaderstaticparms_count;
3774 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3775 fragstrings_count += shaderstaticparms_count;
3777 // now append the shader text itself
3778 vertstrings_list[vertstrings_count++] = vertexstring;
3779 geomstrings_list[geomstrings_count++] = geometrystring;
3780 fragstrings_list[fragstrings_count++] = fragmentstring;
3782 // if any sources were NULL, clear the respective list
3784 vertstrings_count = 0;
3785 if (!geometrystring)
3786 geomstrings_count = 0;
3787 if (!fragmentstring)
3788 fragstrings_count = 0;
3790 // compile the shader program
3791 if (vertstrings_count + geomstrings_count + fragstrings_count)
3792 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3796 qglUseProgramObjectARB(p->program);CHECKGLERROR
3797 // look up all the uniform variable names we care about, so we don't
3798 // have to look them up every time we set them
3800 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
3801 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
3802 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3803 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
3804 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
3805 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3806 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
3807 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3808 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3809 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3810 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3811 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
3812 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3813 p->loc_Texture_FogHeightTexture = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3814 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3815 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3816 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3817 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3818 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
3819 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3820 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3821 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3822 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3823 p->loc_Texture_ScreenDepth = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3824 p->loc_Texture_ScreenNormalMap = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3825 p->loc_Texture_ScreenDiffuse = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3826 p->loc_Texture_ScreenSpecular = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3827 p->loc_Texture_ReflectMask = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3828 p->loc_Texture_ReflectCube = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3829 p->loc_Alpha = qglGetUniformLocationARB(p->program, "Alpha");
3830 p->loc_BloomBlur_Parameters = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3831 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
3832 p->loc_Color_Ambient = qglGetUniformLocationARB(p->program, "Color_Ambient");
3833 p->loc_Color_Diffuse = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3834 p->loc_Color_Specular = qglGetUniformLocationARB(p->program, "Color_Specular");
3835 p->loc_Color_Glow = qglGetUniformLocationARB(p->program, "Color_Glow");
3836 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
3837 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
3838 p->loc_DeferredColor_Ambient = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3839 p->loc_DeferredColor_Diffuse = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3840 p->loc_DeferredColor_Specular = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3841 p->loc_DeferredMod_Diffuse = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3842 p->loc_DeferredMod_Specular = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3843 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3844 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
3845 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
3846 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
3847 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
3848 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3849 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3850 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
3851 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
3852 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
3853 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3854 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
3855 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
3856 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
3857 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
3858 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
3859 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
3860 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3861 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3862 p->loc_ScreenToDepth = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3863 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3864 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3865 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
3866 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
3867 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
3868 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
3869 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
3870 p->loc_ViewTintColor = qglGetUniformLocationARB(p->program, "ViewTintColor");
3871 p->loc_ViewToLight = qglGetUniformLocationARB(p->program, "ViewToLight");
3872 p->loc_ModelToLight = qglGetUniformLocationARB(p->program, "ModelToLight");
3873 p->loc_TexMatrix = qglGetUniformLocationARB(p->program, "TexMatrix");
3874 p->loc_BackgroundTexMatrix = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3875 p->loc_ModelViewMatrix = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3876 p->loc_ModelViewProjectionMatrix = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3877 p->loc_PixelToScreenTexCoord = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3878 p->loc_ModelToReflectCube = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3879 p->loc_ShadowMapMatrix = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3880 p->loc_BloomColorSubtract = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
3881 p->loc_NormalmapScrollBlend = qglGetUniformLocationARB(p->program, "NormalmapScrollBlend");
3882 // initialize the samplers to refer to the texture units we use
3883 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
3884 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
3885 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
3886 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
3887 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
3888 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
3889 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
3890 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3891 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3892 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3893 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
3894 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
3895 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
3896 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3897 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
3898 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
3899 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
3900 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
3901 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
3902 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
3903 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
3904 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
3905 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3906 if (p->loc_Texture_ScreenDepth >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth , GL20TU_SCREENDEPTH);
3907 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3908 if (p->loc_Texture_ScreenDiffuse >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse , GL20TU_SCREENDIFFUSE);
3909 if (p->loc_Texture_ScreenSpecular >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3910 if (p->loc_Texture_ReflectMask >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask , GL20TU_REFLECTMASK);
3911 if (p->loc_Texture_ReflectCube >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube , GL20TU_REFLECTCUBE);
3913 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3916 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
3920 Mem_Free(vertexstring);
3922 Mem_Free(geometrystring);
3924 Mem_Free(fragmentstring);
3927 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3929 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3930 if (r_glsl_permutation != perm)
3932 r_glsl_permutation = perm;
3933 if (!r_glsl_permutation->program)
3935 if (!r_glsl_permutation->compiled)
3936 R_GLSL_CompilePermutation(perm, mode, permutation);
3937 if (!r_glsl_permutation->program)
3939 // remove features until we find a valid permutation
3941 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3943 // reduce i more quickly whenever it would not remove any bits
3944 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3945 if (!(permutation & j))
3948 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3949 if (!r_glsl_permutation->compiled)
3950 R_GLSL_CompilePermutation(perm, mode, permutation);
3951 if (r_glsl_permutation->program)
3954 if (i >= SHADERPERMUTATION_COUNT)
3956 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3957 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3958 qglUseProgramObjectARB(0);CHECKGLERROR
3959 return; // no bit left to clear, entire mode is broken
3964 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3966 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3967 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3968 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3972 #include <Cg/cgGL.h>
3973 struct r_cg_permutation_s;
3974 typedef struct r_cg_permutation_s
3976 /// hash lookup data
3977 struct r_cg_permutation_s *hashnext;
3979 unsigned int permutation;
3981 /// indicates if we have tried compiling this permutation already
3983 /// 0 if compilation failed
3986 /// locations of detected parameters in programs, or NULL if not found
3987 CGparameter vp_EyePosition;
3988 CGparameter vp_FogPlane;
3989 CGparameter vp_LightDir;
3990 CGparameter vp_LightPosition;
3991 CGparameter vp_ModelToLight;
3992 CGparameter vp_TexMatrix;
3993 CGparameter vp_BackgroundTexMatrix;
3994 CGparameter vp_ModelViewProjectionMatrix;
3995 CGparameter vp_ModelViewMatrix;
3996 CGparameter vp_ShadowMapMatrix;
3998 CGparameter fp_Texture_First;
3999 CGparameter fp_Texture_Second;
4000 CGparameter fp_Texture_GammaRamps;
4001 CGparameter fp_Texture_Normal;
4002 CGparameter fp_Texture_Color;
4003 CGparameter fp_Texture_Gloss;
4004 CGparameter fp_Texture_Glow;
4005 CGparameter fp_Texture_SecondaryNormal;
4006 CGparameter fp_Texture_SecondaryColor;
4007 CGparameter fp_Texture_SecondaryGloss;
4008 CGparameter fp_Texture_SecondaryGlow;
4009 CGparameter fp_Texture_Pants;
4010 CGparameter fp_Texture_Shirt;
4011 CGparameter fp_Texture_FogHeightTexture;
4012 CGparameter fp_Texture_FogMask;
4013 CGparameter fp_Texture_Lightmap;
4014 CGparameter fp_Texture_Deluxemap;
4015 CGparameter fp_Texture_Attenuation;
4016 CGparameter fp_Texture_Cube;
4017 CGparameter fp_Texture_Refraction;
4018 CGparameter fp_Texture_Reflection;
4019 CGparameter fp_Texture_ShadowMap2D;
4020 CGparameter fp_Texture_CubeProjection;
4021 CGparameter fp_Texture_ScreenDepth;
4022 CGparameter fp_Texture_ScreenNormalMap;
4023 CGparameter fp_Texture_ScreenDiffuse;
4024 CGparameter fp_Texture_ScreenSpecular;
4025 CGparameter fp_Texture_ReflectMask;
4026 CGparameter fp_Texture_ReflectCube;
4027 CGparameter fp_Alpha;
4028 CGparameter fp_BloomBlur_Parameters;
4029 CGparameter fp_ClientTime;
4030 CGparameter fp_Color_Ambient;
4031 CGparameter fp_Color_Diffuse;
4032 CGparameter fp_Color_Specular;
4033 CGparameter fp_Color_Glow;
4034 CGparameter fp_Color_Pants;
4035 CGparameter fp_Color_Shirt;
4036 CGparameter fp_DeferredColor_Ambient;
4037 CGparameter fp_DeferredColor_Diffuse;
4038 CGparameter fp_DeferredColor_Specular;
4039 CGparameter fp_DeferredMod_Diffuse;
4040 CGparameter fp_DeferredMod_Specular;
4041 CGparameter fp_DistortScaleRefractReflect;
4042 CGparameter fp_EyePosition;
4043 CGparameter fp_FogColor;
4044 CGparameter fp_FogHeightFade;
4045 CGparameter fp_FogPlane;
4046 CGparameter fp_FogPlaneViewDist;
4047 CGparameter fp_FogRangeRecip;
4048 CGparameter fp_LightColor;
4049 CGparameter fp_LightDir;
4050 CGparameter fp_LightPosition;
4051 CGparameter fp_OffsetMapping_Scale;
4052 CGparameter fp_PixelSize;
4053 CGparameter fp_ReflectColor;
4054 CGparameter fp_ReflectFactor;
4055 CGparameter fp_ReflectOffset;
4056 CGparameter fp_RefractColor;
4057 CGparameter fp_Saturation;
4058 CGparameter fp_ScreenCenterRefractReflect;
4059 CGparameter fp_ScreenScaleRefractReflect;
4060 CGparameter fp_ScreenToDepth;
4061 CGparameter fp_ShadowMap_Parameters;
4062 CGparameter fp_ShadowMap_TextureScale;
4063 CGparameter fp_SpecularPower;
4064 CGparameter fp_UserVec1;
4065 CGparameter fp_UserVec2;
4066 CGparameter fp_UserVec3;
4067 CGparameter fp_UserVec4;
4068 CGparameter fp_ViewTintColor;
4069 CGparameter fp_ViewToLight;
4070 CGparameter fp_PixelToScreenTexCoord;
4071 CGparameter fp_ModelToReflectCube;
4072 CGparameter fp_BloomColorSubtract;
4073 CGparameter fp_NormalmapScrollBlend;
4077 /// information about each possible shader permutation
4078 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4079 /// currently selected permutation
4080 r_cg_permutation_t *r_cg_permutation;
4081 /// storage for permutations linked in the hash table
4082 memexpandablearray_t r_cg_permutationarray;
4084 #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));}}
4086 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
4088 //unsigned int hashdepth = 0;
4089 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4090 r_cg_permutation_t *p;
4091 for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4093 if (p->mode == mode && p->permutation == permutation)
4095 //if (hashdepth > 10)
4096 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4101 p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4103 p->permutation = permutation;
4104 p->hashnext = r_cg_permutationhash[mode][hashindex];
4105 r_cg_permutationhash[mode][hashindex] = p;
4106 //if (hashdepth > 10)
4107 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4111 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4114 if (!filename || !filename[0])
4116 if (!strcmp(filename, "cg/default.cg"))
4118 if (!cgshaderstring)
4120 cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4122 Con_DPrintf("Loading shaders from file %s...\n", filename);
4124 cgshaderstring = (char *)builtincgshaderstring;
4126 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4127 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4128 return shaderstring;
4130 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4133 if (printfromdisknotice)
4134 Con_DPrintf("from disk %s... ", filename);
4135 return shaderstring;
4137 return shaderstring;
4140 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4142 // TODO: load or create .fp and .vp shader files
4145 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4148 shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4149 int vertstring_length = 0;
4150 int geomstring_length = 0;
4151 int fragstring_length = 0;
4153 char *vertexstring, *geometrystring, *fragmentstring;
4154 char *vertstring, *geomstring, *fragstring;
4155 char permutationname[256];
4156 char cachename[256];
4157 CGprofile vertexProfile;
4158 CGprofile fragmentProfile;
4159 int vertstrings_count = 0;
4160 int geomstrings_count = 0;
4161 int fragstrings_count = 0;
4162 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4163 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4164 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4172 permutationname[0] = 0;
4174 vertexstring = R_CG_GetText(modeinfo->vertexfilename, true);
4175 geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4176 fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4178 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4179 strlcat(cachename, "cg/", sizeof(cachename));
4181 // the first pretext is which type of shader to compile as
4182 // (later these will all be bound together as a program object)
4183 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4184 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4185 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4187 // the second pretext is the mode (for example a light source)
4188 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4189 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4190 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4191 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4192 strlcat(cachename, modeinfo->name, sizeof(cachename));
4194 // now add all the permutation pretexts
4195 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4197 if (permutation & (1<<i))
4199 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4200 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4201 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4202 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4203 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4207 // keep line numbers correct
4208 vertstrings_list[vertstrings_count++] = "\n";
4209 geomstrings_list[geomstrings_count++] = "\n";
4210 fragstrings_list[fragstrings_count++] = "\n";
4215 R_CompileShader_AddStaticParms(mode, permutation);
4216 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4217 vertstrings_count += shaderstaticparms_count;
4218 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4219 geomstrings_count += shaderstaticparms_count;
4220 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4221 fragstrings_count += shaderstaticparms_count;
4223 // replace spaces in the cachename with _ characters
4224 for (i = 0;cachename[i];i++)
4225 if (cachename[i] == ' ')
4228 // now append the shader text itself
4229 vertstrings_list[vertstrings_count++] = vertexstring;
4230 geomstrings_list[geomstrings_count++] = geometrystring;
4231 fragstrings_list[fragstrings_count++] = fragmentstring;
4233 // if any sources were NULL, clear the respective list
4235 vertstrings_count = 0;
4236 if (!geometrystring)
4237 geomstrings_count = 0;
4238 if (!fragmentstring)
4239 fragstrings_count = 0;
4241 vertstring_length = 0;
4242 for (i = 0;i < vertstrings_count;i++)
4243 vertstring_length += strlen(vertstrings_list[i]);
4244 vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4245 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4246 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4248 geomstring_length = 0;
4249 for (i = 0;i < geomstrings_count;i++)
4250 geomstring_length += strlen(geomstrings_list[i]);
4251 geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4252 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4253 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4255 fragstring_length = 0;
4256 for (i = 0;i < fragstrings_count;i++)
4257 fragstring_length += strlen(fragstrings_list[i]);
4258 fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4259 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4260 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4264 //vertexProfile = CG_PROFILE_ARBVP1;
4265 //fragmentProfile = CG_PROFILE_ARBFP1;
4266 vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4267 fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4268 //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4269 //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4270 //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4273 // try to load the cached shader, or generate one
4274 R_CG_CacheShader(p, cachename, vertstring, fragstring);
4276 // if caching failed, do a dynamic compile for now
4278 if (vertstring[0] && !p->vprogram)
4279 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4281 if (fragstring[0] && !p->fprogram)
4282 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4285 // look up all the uniform variable names we care about, so we don't
4286 // have to look them up every time we set them
4290 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4291 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4292 p->vp_EyePosition = cgGetNamedParameter(p->vprogram, "EyePosition");
4293 p->vp_FogPlane = cgGetNamedParameter(p->vprogram, "FogPlane");
4294 p->vp_LightDir = cgGetNamedParameter(p->vprogram, "LightDir");
4295 p->vp_LightPosition = cgGetNamedParameter(p->vprogram, "LightPosition");
4296 p->vp_ModelToLight = cgGetNamedParameter(p->vprogram, "ModelToLight");
4297 p->vp_TexMatrix = cgGetNamedParameter(p->vprogram, "TexMatrix");
4298 p->vp_BackgroundTexMatrix = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4299 p->vp_ModelViewProjectionMatrix = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4300 p->vp_ModelViewMatrix = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4301 p->vp_ShadowMapMatrix = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4307 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4308 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4309 p->fp_Texture_First = cgGetNamedParameter(p->fprogram, "Texture_First");
4310 p->fp_Texture_Second = cgGetNamedParameter(p->fprogram, "Texture_Second");
4311 p->fp_Texture_GammaRamps = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4312 p->fp_Texture_Normal = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4313 p->fp_Texture_Color = cgGetNamedParameter(p->fprogram, "Texture_Color");
4314 p->fp_Texture_Gloss = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4315 p->fp_Texture_Glow = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4316 p->fp_Texture_SecondaryNormal = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4317 p->fp_Texture_SecondaryColor = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4318 p->fp_Texture_SecondaryGloss = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4319 p->fp_Texture_SecondaryGlow = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4320 p->fp_Texture_Pants = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4321 p->fp_Texture_Shirt = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4322 p->fp_Texture_FogHeightTexture = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4323 p->fp_Texture_FogMask = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4324 p->fp_Texture_Lightmap = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4325 p->fp_Texture_Deluxemap = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4326 p->fp_Texture_Attenuation = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4327 p->fp_Texture_Cube = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4328 p->fp_Texture_Refraction = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4329 p->fp_Texture_Reflection = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4330 p->fp_Texture_ShadowMap2D = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4331 p->fp_Texture_CubeProjection = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4332 p->fp_Texture_ScreenDepth = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4333 p->fp_Texture_ScreenNormalMap = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4334 p->fp_Texture_ScreenDiffuse = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4335 p->fp_Texture_ScreenSpecular = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4336 p->fp_Texture_ReflectMask = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4337 p->fp_Texture_ReflectCube = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4338 p->fp_Alpha = cgGetNamedParameter(p->fprogram, "Alpha");
4339 p->fp_BloomBlur_Parameters = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4340 p->fp_ClientTime = cgGetNamedParameter(p->fprogram, "ClientTime");
4341 p->fp_Color_Ambient = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4342 p->fp_Color_Diffuse = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4343 p->fp_Color_Specular = cgGetNamedParameter(p->fprogram, "Color_Specular");
4344 p->fp_Color_Glow = cgGetNamedParameter(p->fprogram, "Color_Glow");
4345 p->fp_Color_Pants = cgGetNamedParameter(p->fprogram, "Color_Pants");
4346 p->fp_Color_Shirt = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4347 p->fp_DeferredColor_Ambient = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4348 p->fp_DeferredColor_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4349 p->fp_DeferredColor_Specular = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4350 p->fp_DeferredMod_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4351 p->fp_DeferredMod_Specular = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4352 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4353 p->fp_EyePosition = cgGetNamedParameter(p->fprogram, "EyePosition");
4354 p->fp_FogColor = cgGetNamedParameter(p->fprogram, "FogColor");
4355 p->fp_FogHeightFade = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4356 p->fp_FogPlane = cgGetNamedParameter(p->fprogram, "FogPlane");
4357 p->fp_FogPlaneViewDist = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4358 p->fp_FogRangeRecip = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4359 p->fp_LightColor = cgGetNamedParameter(p->fprogram, "LightColor");
4360 p->fp_LightDir = cgGetNamedParameter(p->fprogram, "LightDir");
4361 p->fp_LightPosition = cgGetNamedParameter(p->fprogram, "LightPosition");
4362 p->fp_OffsetMapping_Scale = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4363 p->fp_PixelSize = cgGetNamedParameter(p->fprogram, "PixelSize");
4364 p->fp_ReflectColor = cgGetNamedParameter(p->fprogram, "ReflectColor");
4365 p->fp_ReflectFactor = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4366 p->fp_ReflectOffset = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4367 p->fp_RefractColor = cgGetNamedParameter(p->fprogram, "RefractColor");
4368 p->fp_Saturation = cgGetNamedParameter(p->fprogram, "Saturation");
4369 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4370 p->fp_ScreenScaleRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4371 p->fp_ScreenToDepth = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4372 p->fp_ShadowMap_Parameters = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4373 p->fp_ShadowMap_TextureScale = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4374 p->fp_SpecularPower = cgGetNamedParameter(p->fprogram, "SpecularPower");
4375 p->fp_UserVec1 = cgGetNamedParameter(p->fprogram, "UserVec1");
4376 p->fp_UserVec2 = cgGetNamedParameter(p->fprogram, "UserVec2");
4377 p->fp_UserVec3 = cgGetNamedParameter(p->fprogram, "UserVec3");
4378 p->fp_UserVec4 = cgGetNamedParameter(p->fprogram, "UserVec4");
4379 p->fp_ViewTintColor = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4380 p->fp_ViewToLight = cgGetNamedParameter(p->fprogram, "ViewToLight");
4381 p->fp_PixelToScreenTexCoord = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4382 p->fp_ModelToReflectCube = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4383 p->fp_BloomColorSubtract = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4384 p->fp_NormalmapScrollBlend = cgGetNamedParameter(p->fprogram, "NormalmapScrollBlend");
4388 if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4389 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4391 Con_Printf("^1CG shader %s failed! some features may not work properly.\n", permutationname);
4395 Mem_Free(vertstring);
4397 Mem_Free(geomstring);
4399 Mem_Free(fragstring);
4401 Mem_Free(vertexstring);
4403 Mem_Free(geometrystring);
4405 Mem_Free(fragmentstring);
4408 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4410 r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4413 if (r_cg_permutation != perm)
4415 r_cg_permutation = perm;
4416 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4418 if (!r_cg_permutation->compiled)
4419 R_CG_CompilePermutation(perm, mode, permutation);
4420 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4422 // remove features until we find a valid permutation
4424 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4426 // reduce i more quickly whenever it would not remove any bits
4427 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4428 if (!(permutation & j))
4431 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4432 if (!r_cg_permutation->compiled)
4433 R_CG_CompilePermutation(perm, mode, permutation);
4434 if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4437 if (i >= SHADERPERMUTATION_COUNT)
4439 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4440 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4441 return; // no bit left to clear, entire mode is broken
4447 if (r_cg_permutation->vprogram)
4449 cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4450 cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4451 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4455 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4456 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4458 if (r_cg_permutation->fprogram)
4460 cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4461 cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4462 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4466 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4467 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4471 if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4472 if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4473 if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4476 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4478 cgGLSetTextureParameter(param, R_GetTexture(tex));
4479 cgGLEnableTextureParameter(param);
4487 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4488 extern D3DCAPS9 vid_d3d9caps;
4491 struct r_hlsl_permutation_s;
4492 typedef struct r_hlsl_permutation_s
4494 /// hash lookup data
4495 struct r_hlsl_permutation_s *hashnext;
4497 unsigned int permutation;
4499 /// indicates if we have tried compiling this permutation already
4501 /// NULL if compilation failed
4502 IDirect3DVertexShader9 *vertexshader;
4503 IDirect3DPixelShader9 *pixelshader;
4505 r_hlsl_permutation_t;
4507 typedef enum D3DVSREGISTER_e
4509 D3DVSREGISTER_TexMatrix = 0, // float4x4
4510 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4511 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4512 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4513 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4514 D3DVSREGISTER_ModelToLight = 20, // float4x4
4515 D3DVSREGISTER_EyePosition = 24,
4516 D3DVSREGISTER_FogPlane = 25,
4517 D3DVSREGISTER_LightDir = 26,
4518 D3DVSREGISTER_LightPosition = 27,
4522 typedef enum D3DPSREGISTER_e
4524 D3DPSREGISTER_Alpha = 0,
4525 D3DPSREGISTER_BloomBlur_Parameters = 1,
4526 D3DPSREGISTER_ClientTime = 2,
4527 D3DPSREGISTER_Color_Ambient = 3,
4528 D3DPSREGISTER_Color_Diffuse = 4,
4529 D3DPSREGISTER_Color_Specular = 5,
4530 D3DPSREGISTER_Color_Glow = 6,
4531 D3DPSREGISTER_Color_Pants = 7,
4532 D3DPSREGISTER_Color_Shirt = 8,
4533 D3DPSREGISTER_DeferredColor_Ambient = 9,
4534 D3DPSREGISTER_DeferredColor_Diffuse = 10,
4535 D3DPSREGISTER_DeferredColor_Specular = 11,
4536 D3DPSREGISTER_DeferredMod_Diffuse = 12,
4537 D3DPSREGISTER_DeferredMod_Specular = 13,
4538 D3DPSREGISTER_DistortScaleRefractReflect = 14,
4539 D3DPSREGISTER_EyePosition = 15, // unused
4540 D3DPSREGISTER_FogColor = 16,
4541 D3DPSREGISTER_FogHeightFade = 17,
4542 D3DPSREGISTER_FogPlane = 18,
4543 D3DPSREGISTER_FogPlaneViewDist = 19,
4544 D3DPSREGISTER_FogRangeRecip = 20,
4545 D3DPSREGISTER_LightColor = 21,
4546 D3DPSREGISTER_LightDir = 22, // unused
4547 D3DPSREGISTER_LightPosition = 23,
4548 D3DPSREGISTER_OffsetMapping_Scale = 24,
4549 D3DPSREGISTER_PixelSize = 25,
4550 D3DPSREGISTER_ReflectColor = 26,
4551 D3DPSREGISTER_ReflectFactor = 27,
4552 D3DPSREGISTER_ReflectOffset = 28,
4553 D3DPSREGISTER_RefractColor = 29,
4554 D3DPSREGISTER_Saturation = 30,
4555 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4556 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4557 D3DPSREGISTER_ScreenToDepth = 33,
4558 D3DPSREGISTER_ShadowMap_Parameters = 34,
4559 D3DPSREGISTER_ShadowMap_TextureScale = 35,
4560 D3DPSREGISTER_SpecularPower = 36,
4561 D3DPSREGISTER_UserVec1 = 37,
4562 D3DPSREGISTER_UserVec2 = 38,
4563 D3DPSREGISTER_UserVec3 = 39,
4564 D3DPSREGISTER_UserVec4 = 40,
4565 D3DPSREGISTER_ViewTintColor = 41,
4566 D3DPSREGISTER_PixelToScreenTexCoord = 42,
4567 D3DPSREGISTER_BloomColorSubtract = 43,
4568 D3DPSREGISTER_ViewToLight = 44, // float4x4
4569 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4570 D3DPSREGISTER_NormalmapScrollBlend = 52,
4575 /// information about each possible shader permutation
4576 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4577 /// currently selected permutation
4578 r_hlsl_permutation_t *r_hlsl_permutation;
4579 /// storage for permutations linked in the hash table
4580 memexpandablearray_t r_hlsl_permutationarray;
4582 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4584 //unsigned int hashdepth = 0;
4585 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4586 r_hlsl_permutation_t *p;
4587 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4589 if (p->mode == mode && p->permutation == permutation)
4591 //if (hashdepth > 10)
4592 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4597 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4599 p->permutation = permutation;
4600 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4601 r_hlsl_permutationhash[mode][hashindex] = p;
4602 //if (hashdepth > 10)
4603 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4607 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4610 if (!filename || !filename[0])
4612 if (!strcmp(filename, "hlsl/default.hlsl"))
4614 if (!hlslshaderstring)
4616 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4617 if (hlslshaderstring)
4618 Con_DPrintf("Loading shaders from file %s...\n", filename);
4620 hlslshaderstring = (char *)builtincgshaderstring;
4622 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4623 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4624 return shaderstring;
4626 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4629 if (printfromdisknotice)
4630 Con_DPrintf("from disk %s... ", filename);
4631 return shaderstring;
4633 return shaderstring;
4637 //#include <d3dx9shader.h>
4638 //#include <d3dx9mesh.h>
4640 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4642 DWORD *vsbin = NULL;
4643 DWORD *psbin = NULL;
4644 fs_offset_t vsbinsize;
4645 fs_offset_t psbinsize;
4646 // IDirect3DVertexShader9 *vs = NULL;
4647 // IDirect3DPixelShader9 *ps = NULL;
4648 ID3DXBuffer *vslog = NULL;
4649 ID3DXBuffer *vsbuffer = NULL;
4650 ID3DXConstantTable *vsconstanttable = NULL;
4651 ID3DXBuffer *pslog = NULL;
4652 ID3DXBuffer *psbuffer = NULL;
4653 ID3DXConstantTable *psconstanttable = NULL;
4656 char temp[MAX_INPUTLINE];
4657 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4658 qboolean debugshader = gl_paranoid.integer != 0;
4659 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4660 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4663 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4664 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4666 if ((!vsbin && vertstring) || (!psbin && fragstring))
4668 const char* dllnames_d3dx9 [] =
4692 dllhandle_t d3dx9_dll = NULL;
4693 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4694 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4695 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4696 dllfunction_t d3dx9_dllfuncs[] =
4698 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
4699 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
4700 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
4703 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4705 DWORD shaderflags = 0;
4707 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4708 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4709 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4710 if (vertstring && vertstring[0])
4714 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4715 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4716 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4717 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4720 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4723 vsbinsize = vsbuffer->GetBufferSize();
4724 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4725 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4726 vsbuffer->Release();
4730 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4731 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4735 if (fragstring && fragstring[0])
4739 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4740 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4741 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4742 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4745 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4748 psbinsize = psbuffer->GetBufferSize();
4749 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4750 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4751 psbuffer->Release();
4755 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4756 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4760 Sys_UnloadLibrary(&d3dx9_dll);
4763 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4767 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4768 if (FAILED(vsresult))
4769 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4770 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4771 if (FAILED(psresult))
4772 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4774 // free the shader data
4775 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4776 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4779 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4782 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4783 int vertstring_length = 0;
4784 int geomstring_length = 0;
4785 int fragstring_length = 0;
4787 char *vertexstring, *geometrystring, *fragmentstring;
4788 char *vertstring, *geomstring, *fragstring;
4789 char permutationname[256];
4790 char cachename[256];
4791 int vertstrings_count = 0;
4792 int geomstrings_count = 0;
4793 int fragstrings_count = 0;
4794 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4795 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4796 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4801 p->vertexshader = NULL;
4802 p->pixelshader = NULL;
4804 permutationname[0] = 0;
4806 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
4807 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4808 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4810 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4811 strlcat(cachename, "hlsl/", sizeof(cachename));
4813 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4814 vertstrings_count = 0;
4815 geomstrings_count = 0;
4816 fragstrings_count = 0;
4817 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4818 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4819 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4821 // the first pretext is which type of shader to compile as
4822 // (later these will all be bound together as a program object)
4823 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4824 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4825 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4827 // the second pretext is the mode (for example a light source)
4828 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4829 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4830 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4831 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4832 strlcat(cachename, modeinfo->name, sizeof(cachename));
4834 // now add all the permutation pretexts
4835 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4837 if (permutation & (1<<i))
4839 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4840 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4841 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4842 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4843 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4847 // keep line numbers correct
4848 vertstrings_list[vertstrings_count++] = "\n";
4849 geomstrings_list[geomstrings_count++] = "\n";
4850 fragstrings_list[fragstrings_count++] = "\n";
4855 R_CompileShader_AddStaticParms(mode, permutation);
4856 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4857 vertstrings_count += shaderstaticparms_count;
4858 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4859 geomstrings_count += shaderstaticparms_count;
4860 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4861 fragstrings_count += shaderstaticparms_count;
4863 // replace spaces in the cachename with _ characters
4864 for (i = 0;cachename[i];i++)
4865 if (cachename[i] == ' ')
4868 // now append the shader text itself
4869 vertstrings_list[vertstrings_count++] = vertexstring;
4870 geomstrings_list[geomstrings_count++] = geometrystring;
4871 fragstrings_list[fragstrings_count++] = fragmentstring;
4873 // if any sources were NULL, clear the respective list
4875 vertstrings_count = 0;
4876 if (!geometrystring)
4877 geomstrings_count = 0;
4878 if (!fragmentstring)
4879 fragstrings_count = 0;
4881 vertstring_length = 0;
4882 for (i = 0;i < vertstrings_count;i++)
4883 vertstring_length += strlen(vertstrings_list[i]);
4884 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4885 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4886 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4888 geomstring_length = 0;
4889 for (i = 0;i < geomstrings_count;i++)
4890 geomstring_length += strlen(geomstrings_list[i]);
4891 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4892 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4893 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4895 fragstring_length = 0;
4896 for (i = 0;i < fragstrings_count;i++)
4897 fragstring_length += strlen(fragstrings_list[i]);
4898 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4899 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4900 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4902 // try to load the cached shader, or generate one
4903 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4905 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4906 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4908 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
4912 Mem_Free(vertstring);
4914 Mem_Free(geomstring);
4916 Mem_Free(fragstring);
4918 Mem_Free(vertexstring);
4920 Mem_Free(geometrystring);
4922 Mem_Free(fragmentstring);
4925 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4926 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4927 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);}
4928 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);}
4929 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);}
4930 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);}
4932 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4933 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4934 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);}
4935 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);}
4936 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);}
4937 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);}
4939 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4941 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4942 if (r_hlsl_permutation != perm)
4944 r_hlsl_permutation = perm;
4945 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4947 if (!r_hlsl_permutation->compiled)
4948 R_HLSL_CompilePermutation(perm, mode, permutation);
4949 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4951 // remove features until we find a valid permutation
4953 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4955 // reduce i more quickly whenever it would not remove any bits
4956 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4957 if (!(permutation & j))
4960 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4961 if (!r_hlsl_permutation->compiled)
4962 R_HLSL_CompilePermutation(perm, mode, permutation);
4963 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4966 if (i >= SHADERPERMUTATION_COUNT)
4968 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4969 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4970 return; // no bit left to clear, entire mode is broken
4974 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4975 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4977 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4978 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4979 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4983 void R_GLSL_Restart_f(void)
4985 unsigned int i, limit;
4986 if (glslshaderstring && glslshaderstring != builtinshaderstring)
4987 Mem_Free(glslshaderstring);
4988 glslshaderstring = NULL;
4989 if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4990 Mem_Free(cgshaderstring);
4991 cgshaderstring = NULL;
4992 if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
4993 Mem_Free(hlslshaderstring);
4994 hlslshaderstring = NULL;
4995 switch(vid.renderpath)
4997 case RENDERPATH_D3D9:
5000 r_hlsl_permutation_t *p;
5001 r_hlsl_permutation = NULL;
5002 // cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5003 // cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5004 // cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5005 // cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5006 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
5007 for (i = 0;i < limit;i++)
5009 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
5011 if (p->vertexshader)
5012 IDirect3DVertexShader9_Release(p->vertexshader);
5014 IDirect3DPixelShader9_Release(p->pixelshader);
5015 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
5018 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
5022 case RENDERPATH_D3D10:
5023 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5025 case RENDERPATH_D3D11:
5026 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5028 case RENDERPATH_GL20:
5030 r_glsl_permutation_t *p;
5031 r_glsl_permutation = NULL;
5032 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
5033 for (i = 0;i < limit;i++)
5035 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
5037 GL_Backend_FreeProgram(p->program);
5038 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
5041 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5044 case RENDERPATH_CGGL:
5047 r_cg_permutation_t *p;
5048 r_cg_permutation = NULL;
5049 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5050 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5051 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5052 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5053 limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
5054 for (i = 0;i < limit;i++)
5056 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
5059 cgDestroyProgram(p->vprogram);
5061 cgDestroyProgram(p->fprogram);
5062 Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
5065 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5069 case RENDERPATH_GL13:
5070 case RENDERPATH_GL11:
5075 void R_GLSL_DumpShader_f(void)
5080 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
5083 FS_Print(file, "/* The engine may define the following macros:\n");
5084 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5085 for (i = 0;i < SHADERMODE_COUNT;i++)
5086 FS_Print(file, glslshadermodeinfo[i].pretext);
5087 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5088 FS_Print(file, shaderpermutationinfo[i].pretext);
5089 FS_Print(file, "*/\n");
5090 FS_Print(file, builtinshaderstring);
5092 Con_Printf("glsl/default.glsl written\n");
5095 Con_Printf("failed to write to glsl/default.glsl\n");
5098 file = FS_OpenRealFile("cg/default.cg", "w", false);
5101 FS_Print(file, "/* The engine may define the following macros:\n");
5102 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5103 for (i = 0;i < SHADERMODE_COUNT;i++)
5104 FS_Print(file, cgshadermodeinfo[i].pretext);
5105 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5106 FS_Print(file, shaderpermutationinfo[i].pretext);
5107 FS_Print(file, "*/\n");
5108 FS_Print(file, builtincgshaderstring);
5110 Con_Printf("cg/default.cg written\n");
5113 Con_Printf("failed to write to cg/default.cg\n");
5117 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
5120 FS_Print(file, "/* The engine may define the following macros:\n");
5121 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5122 for (i = 0;i < SHADERMODE_COUNT;i++)
5123 FS_Print(file, hlslshadermodeinfo[i].pretext);
5124 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5125 FS_Print(file, shaderpermutationinfo[i].pretext);
5126 FS_Print(file, "*/\n");
5127 FS_Print(file, builtincgshaderstring);
5129 Con_Printf("hlsl/default.hlsl written\n");
5132 Con_Printf("failed to write to hlsl/default.hlsl\n");
5136 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
5139 texturemode = GL_MODULATE;
5140 switch (vid.renderpath)
5142 case RENDERPATH_D3D9:
5144 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5145 R_Mesh_TexBind(GL20TU_FIRST , first );
5146 R_Mesh_TexBind(GL20TU_SECOND, second);
5149 case RENDERPATH_D3D10:
5150 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5152 case RENDERPATH_D3D11:
5153 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5155 case RENDERPATH_GL20:
5156 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5157 R_Mesh_TexBind(GL20TU_FIRST , first );
5158 R_Mesh_TexBind(GL20TU_SECOND, second);
5160 case RENDERPATH_CGGL:
5163 R_SetupShader_SetPermutationCG(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5164 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
5165 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
5168 case RENDERPATH_GL13:
5169 R_Mesh_TexBind(0, first );
5170 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
5171 R_Mesh_TexBind(1, second);
5173 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
5175 case RENDERPATH_GL11:
5176 R_Mesh_TexBind(0, first );
5181 void R_SetupShader_DepthOrShadow(void)
5183 switch (vid.renderpath)
5185 case RENDERPATH_D3D9:
5187 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5190 case RENDERPATH_D3D10:
5191 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5193 case RENDERPATH_D3D11:
5194 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5196 case RENDERPATH_GL20:
5197 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5199 case RENDERPATH_CGGL:
5201 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5204 case RENDERPATH_GL13:
5205 R_Mesh_TexBind(0, 0);
5206 R_Mesh_TexBind(1, 0);
5208 case RENDERPATH_GL11:
5209 R_Mesh_TexBind(0, 0);
5214 void R_SetupShader_ShowDepth(void)
5216 switch (vid.renderpath)
5218 case RENDERPATH_D3D9:
5220 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5223 case RENDERPATH_D3D10:
5224 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5226 case RENDERPATH_D3D11:
5227 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5229 case RENDERPATH_GL20:
5230 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5232 case RENDERPATH_CGGL:
5234 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5237 case RENDERPATH_GL13:
5239 case RENDERPATH_GL11:
5244 extern qboolean r_shadow_usingdeferredprepass;
5245 extern cvar_t r_shadow_deferred_8bitrange;
5246 extern rtexture_t *r_shadow_attenuationgradienttexture;
5247 extern rtexture_t *r_shadow_attenuation2dtexture;
5248 extern rtexture_t *r_shadow_attenuation3dtexture;
5249 extern qboolean r_shadow_usingshadowmap2d;
5250 extern qboolean r_shadow_usingshadowmaportho;
5251 extern float r_shadow_shadowmap_texturescale[2];
5252 extern float r_shadow_shadowmap_parameters[4];
5253 extern qboolean r_shadow_shadowmapvsdct;
5254 extern qboolean r_shadow_shadowmapsampler;
5255 extern int r_shadow_shadowmappcf;
5256 extern rtexture_t *r_shadow_shadowmap2dtexture;
5257 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5258 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5259 extern matrix4x4_t r_shadow_shadowmapmatrix;
5260 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5261 extern int r_shadow_prepass_width;
5262 extern int r_shadow_prepass_height;
5263 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5264 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5265 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
5266 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5267 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5268 extern cvar_t gl_mesh_separatearrays;
5269 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5271 // a blendfunc allows colormod if:
5272 // a) it can never keep the destination pixel invariant, or
5273 // b) it can keep the destination pixel invariant, and still can do so if colormodded
5274 // this is to prevent unintended side effects from colormod
5277 // IF there is a (s, sa) for which for all (d, da),
5278 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5279 // THEN, for this (s, sa) and all (colormod, d, da):
5280 // s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5281 // OBVIOUSLY, this means that
5282 // s*colormod * src(s*colormod, d, sa, da) = 0
5283 // dst(s*colormod, d, sa, da) = 1
5285 // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5287 // main condition to leave dst color invariant:
5288 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5290 // s * 0 + d * dst(s, d, sa, da) == d
5291 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5292 // => colormod is a problem for GL_SRC_COLOR only
5294 // s + d * dst(s, d, sa, da) == d
5296 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5297 // => colormod is never problematic for these
5298 // src == GL_SRC_COLOR:
5299 // s*s + d * dst(s, d, sa, da) == d
5301 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5302 // => colormod is never problematic for these
5303 // src == GL_ONE_MINUS_SRC_COLOR:
5304 // s*(1-s) + d * dst(s, d, sa, da) == d
5305 // => s == 0 or s == 1
5306 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5307 // => colormod is a problem for GL_SRC_COLOR only
5308 // src == GL_DST_COLOR
5309 // s*d + d * dst(s, d, sa, da) == d
5311 // => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5312 // => colormod is always a problem
5315 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5316 // => colormod is never problematic for these
5317 // => BUT, we do not know s! We must assume it is problematic
5318 // then... except in GL_ONE case, where we know all invariant
5320 // src == GL_ONE_MINUS_DST_COLOR
5321 // s*(1-d) + d * dst(s, d, sa, da) == d
5322 // => s == 0 (1-d is impossible to handle for our desired result)
5323 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5324 // => colormod is never problematic for these
5325 // src == GL_SRC_ALPHA
5326 // s*sa + d * dst(s, d, sa, da) == d
5327 // => s == 0, or sa == 0
5328 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5329 // => colormod breaks in the case GL_SRC_COLOR only
5330 // src == GL_ONE_MINUS_SRC_ALPHA
5331 // s*(1-sa) + d * dst(s, d, sa, da) == d
5332 // => s == 0, or sa == 1
5333 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5334 // => colormod breaks in the case GL_SRC_COLOR only
5335 // src == GL_DST_ALPHA
5336 // s*da + d * dst(s, d, sa, da) == d
5338 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5339 // => colormod is never problematic for these
5344 case GL_ONE_MINUS_SRC_COLOR:
5346 case GL_ONE_MINUS_SRC_ALPHA:
5347 if(dst == GL_SRC_COLOR)
5352 case GL_ONE_MINUS_DST_COLOR:
5354 case GL_ONE_MINUS_DST_ALPHA:
5364 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)
5366 // select a permutation of the lighting shader appropriate to this
5367 // combination of texture, entity, light source, and fogging, only use the
5368 // minimum features necessary to avoid wasting rendering time in the
5369 // fragment shader on features that are not being used
5370 unsigned int permutation = 0;
5371 unsigned int mode = 0;
5372 qboolean allow_colormod;
5373 static float dummy_colormod[3] = {1, 1, 1};
5374 float *colormod = rsurface.colormod;
5376 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5377 if (rsurfacepass == RSURFPASS_BACKGROUND)
5379 // distorted background
5380 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5382 mode = SHADERMODE_WATER;
5383 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
5384 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
5385 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5386 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5388 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5390 mode = SHADERMODE_REFRACTION;
5391 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5392 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5396 mode = SHADERMODE_GENERIC;
5397 permutation |= SHADERPERMUTATION_DIFFUSE;
5398 GL_BlendFunc(GL_ONE, GL_ZERO);
5399 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5401 GL_AlphaTest(false);
5403 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5405 if (r_glsl_offsetmapping.integer)
5407 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5408 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5409 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5410 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5411 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5413 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5414 if (r_glsl_offsetmapping_reliefmapping.integer)
5415 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5418 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5419 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5420 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5421 permutation |= SHADERPERMUTATION_ALPHAKILL;
5422 // normalmap (deferred prepass), may use alpha test on diffuse
5423 mode = SHADERMODE_DEFERREDGEOMETRY;
5424 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5425 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5426 GL_AlphaTest(false);
5427 GL_BlendFunc(GL_ONE, GL_ZERO);
5428 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5430 else if (rsurfacepass == RSURFPASS_RTLIGHT)
5432 if (r_glsl_offsetmapping.integer)
5434 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5435 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5436 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5437 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5438 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5440 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5441 if (r_glsl_offsetmapping_reliefmapping.integer)
5442 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5445 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5446 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5448 mode = SHADERMODE_LIGHTSOURCE;
5449 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5450 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5451 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5452 permutation |= SHADERPERMUTATION_CUBEFILTER;
5453 if (diffusescale > 0)
5454 permutation |= SHADERPERMUTATION_DIFFUSE;
5455 if (specularscale > 0)
5456 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5457 if (r_refdef.fogenabled)
5458 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5459 if (rsurface.texture->colormapping)
5460 permutation |= SHADERPERMUTATION_COLORMAPPING;
5461 if (r_shadow_usingshadowmap2d)
5463 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5464 if(r_shadow_shadowmapvsdct)
5465 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5467 if (r_shadow_shadowmapsampler)
5468 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5469 if (r_shadow_shadowmappcf > 1)
5470 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5471 else if (r_shadow_shadowmappcf)
5472 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5474 if (rsurface.texture->reflectmasktexture)
5475 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5476 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5477 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5478 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5480 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5482 if (r_glsl_offsetmapping.integer)
5484 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5485 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5486 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5487 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5488 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5490 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5491 if (r_glsl_offsetmapping_reliefmapping.integer)
5492 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5495 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5496 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5497 // unshaded geometry (fullbright or ambient model lighting)
5498 mode = SHADERMODE_FLATCOLOR;
5499 ambientscale = diffusescale = specularscale = 0;
5500 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5501 permutation |= SHADERPERMUTATION_GLOW;
5502 if (r_refdef.fogenabled)
5503 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5504 if (rsurface.texture->colormapping)
5505 permutation |= SHADERPERMUTATION_COLORMAPPING;
5506 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5508 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5509 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5511 if (r_shadow_shadowmapsampler)
5512 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5513 if (r_shadow_shadowmappcf > 1)
5514 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5515 else if (r_shadow_shadowmappcf)
5516 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5518 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5519 permutation |= SHADERPERMUTATION_REFLECTION;
5520 if (rsurface.texture->reflectmasktexture)
5521 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5522 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5523 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5524 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5526 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5528 if (r_glsl_offsetmapping.integer)
5530 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5531 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5532 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5533 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5534 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5536 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5537 if (r_glsl_offsetmapping_reliefmapping.integer)
5538 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5541 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5542 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5543 // directional model lighting
5544 mode = SHADERMODE_LIGHTDIRECTION;
5545 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5546 permutation |= SHADERPERMUTATION_GLOW;
5547 permutation |= SHADERPERMUTATION_DIFFUSE;
5548 if (specularscale > 0)
5549 permutation |= SHADERPERMUTATION_SPECULAR;
5550 if (r_refdef.fogenabled)
5551 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5552 if (rsurface.texture->colormapping)
5553 permutation |= SHADERPERMUTATION_COLORMAPPING;
5554 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5556 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5557 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5559 if (r_shadow_shadowmapsampler)
5560 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5561 if (r_shadow_shadowmappcf > 1)
5562 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5563 else if (r_shadow_shadowmappcf)
5564 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5566 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5567 permutation |= SHADERPERMUTATION_REFLECTION;
5568 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5569 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5570 if (rsurface.texture->reflectmasktexture)
5571 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5572 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5573 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5574 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5576 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5578 if (r_glsl_offsetmapping.integer)
5580 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5581 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5582 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5583 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5584 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5586 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5587 if (r_glsl_offsetmapping_reliefmapping.integer)
5588 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5591 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5592 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5593 // ambient model lighting
5594 mode = SHADERMODE_LIGHTDIRECTION;
5595 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5596 permutation |= SHADERPERMUTATION_GLOW;
5597 if (r_refdef.fogenabled)
5598 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5599 if (rsurface.texture->colormapping)
5600 permutation |= SHADERPERMUTATION_COLORMAPPING;
5601 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5603 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5604 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5606 if (r_shadow_shadowmapsampler)
5607 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5608 if (r_shadow_shadowmappcf > 1)
5609 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5610 else if (r_shadow_shadowmappcf)
5611 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5613 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5614 permutation |= SHADERPERMUTATION_REFLECTION;
5615 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5616 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5617 if (rsurface.texture->reflectmasktexture)
5618 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5619 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5620 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5621 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5625 if (r_glsl_offsetmapping.integer)
5627 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5628 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5629 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5630 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5631 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5633 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5634 if (r_glsl_offsetmapping_reliefmapping.integer)
5635 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5638 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5639 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5641 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5642 permutation |= SHADERPERMUTATION_GLOW;
5643 if (r_refdef.fogenabled)
5644 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5645 if (rsurface.texture->colormapping)
5646 permutation |= SHADERPERMUTATION_COLORMAPPING;
5647 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5649 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5650 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5652 if (r_shadow_shadowmapsampler)
5653 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5654 if (r_shadow_shadowmappcf > 1)
5655 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5656 else if (r_shadow_shadowmappcf)
5657 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5659 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5660 permutation |= SHADERPERMUTATION_REFLECTION;
5661 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5662 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5663 if (rsurface.texture->reflectmasktexture)
5664 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5665 if (FAKELIGHT_ENABLED)
5667 // fake lightmapping (q1bsp, q3bsp, fullbright map)
5668 mode = SHADERMODE_FAKELIGHT;
5669 permutation |= SHADERPERMUTATION_DIFFUSE;
5670 if (specularscale > 0)
5671 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5673 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5675 // deluxemapping (light direction texture)
5676 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5677 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5679 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5680 permutation |= SHADERPERMUTATION_DIFFUSE;
5681 if (specularscale > 0)
5682 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5684 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5686 // fake deluxemapping (uniform light direction in tangentspace)
5687 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5688 permutation |= SHADERPERMUTATION_DIFFUSE;
5689 if (specularscale > 0)
5690 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5692 else if (rsurface.uselightmaptexture)
5694 // ordinary lightmapping (q1bsp, q3bsp)
5695 mode = SHADERMODE_LIGHTMAP;
5699 // ordinary vertex coloring (q3bsp)
5700 mode = SHADERMODE_VERTEXCOLOR;
5702 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5703 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5704 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5707 colormod = dummy_colormod;
5708 switch(vid.renderpath)
5710 case RENDERPATH_D3D9:
5712 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);
5713 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5714 R_SetupShader_SetPermutationHLSL(mode, permutation);
5715 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5716 if (mode == SHADERMODE_LIGHTSOURCE)
5718 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5719 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5723 if (mode == SHADERMODE_LIGHTDIRECTION)
5725 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5728 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5729 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5730 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5731 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5732 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5734 if (mode == SHADERMODE_LIGHTSOURCE)
5736 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5737 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5738 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5739 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5740 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5742 // additive passes are only darkened by fog, not tinted
5743 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5744 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5748 if (mode == SHADERMODE_FLATCOLOR)
5750 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5752 else if (mode == SHADERMODE_LIGHTDIRECTION)
5754 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]);
5755 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5756 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);
5757 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);
5758 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5759 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5760 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5764 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5765 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5766 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);
5767 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);
5768 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5770 // additive passes are only darkened by fog, not tinted
5771 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5772 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5774 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5775 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);
5776 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5777 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5778 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5779 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5780 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5781 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5782 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5783 if (mode == SHADERMODE_WATER)
5784 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5786 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5787 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5788 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5789 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));
5790 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5791 if (rsurface.texture->pantstexture)
5792 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5794 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5795 if (rsurface.texture->shirttexture)
5796 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5798 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5799 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5800 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5801 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5802 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5803 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5804 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5805 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5807 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5808 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5809 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5810 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5811 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5812 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5813 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5814 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5815 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5816 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5817 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5818 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5819 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5820 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5821 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5822 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5823 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5824 if (rsurfacepass == RSURFPASS_BACKGROUND)
5826 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5827 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5828 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5832 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5834 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5835 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5836 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5837 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5838 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5840 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5841 if (rsurface.rtlight)
5843 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5844 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5849 case RENDERPATH_D3D10:
5850 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5852 case RENDERPATH_D3D11:
5853 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5855 case RENDERPATH_GL20:
5856 if (gl_mesh_separatearrays.integer)
5858 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);
5859 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5860 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5861 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5862 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5863 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5864 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5865 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5869 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);
5870 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5872 R_SetupShader_SetPermutationGLSL(mode, permutation);
5873 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5874 if (mode == SHADERMODE_LIGHTSOURCE)
5876 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5877 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5878 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5879 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5880 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5881 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);
5883 // additive passes are only darkened by fog, not tinted
5884 if (r_glsl_permutation->loc_FogColor >= 0)
5885 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5886 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5890 if (mode == SHADERMODE_FLATCOLOR)
5892 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5894 else if (mode == SHADERMODE_LIGHTDIRECTION)
5896 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]);
5897 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]);
5898 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);
5899 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);
5900 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);
5901 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]);
5902 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]);
5906 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]);
5907 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]);
5908 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);
5909 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);
5910 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);
5912 // additive passes are only darkened by fog, not tinted
5913 if (r_glsl_permutation->loc_FogColor >= 0)
5915 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5916 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5918 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5920 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);
5921 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]);
5922 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]);
5923 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]);
5924 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]);
5925 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5926 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5927 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5928 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]);
5930 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5931 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5932 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5933 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]);
5934 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]);
5936 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5937 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));
5938 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5939 if (r_glsl_permutation->loc_Color_Pants >= 0)
5941 if (rsurface.texture->pantstexture)
5942 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5944 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5946 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5948 if (rsurface.texture->shirttexture)
5949 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5951 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5953 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]);
5954 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5955 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5956 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5957 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5958 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]);
5959 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5961 // if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_texture_white );
5962 // if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_texture_white );
5963 // if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS , r_texture_gammaramps );
5964 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5965 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5966 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5967 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5968 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5969 if (r_glsl_permutation->loc_Texture_SecondaryColor >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5970 if (r_glsl_permutation->loc_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5971 if (r_glsl_permutation->loc_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5972 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5973 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5974 if (r_glsl_permutation->loc_Texture_ReflectMask >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5975 if (r_glsl_permutation->loc_Texture_ReflectCube >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5976 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5977 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5978 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5979 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5980 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5981 if (rsurfacepass == RSURFPASS_BACKGROUND)
5983 if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5984 else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5985 if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5989 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5991 // if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5992 // if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5993 if (r_glsl_permutation->loc_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5994 if (r_glsl_permutation->loc_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5995 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5997 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture );
5998 if (rsurface.rtlight)
6000 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
6001 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
6006 case RENDERPATH_CGGL:
6008 if (gl_mesh_separatearrays.integer)
6010 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);
6011 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
6012 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
6013 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
6014 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
6015 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
6016 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
6017 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
6021 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);
6022 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
6024 R_SetupShader_SetPermutationCG(mode, permutation);
6025 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
6026 if (mode == SHADERMODE_LIGHTSOURCE)
6028 if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
6029 if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6033 if (mode == SHADERMODE_LIGHTDIRECTION)
6035 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
6038 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
6039 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
6040 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
6041 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6042 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
6045 if (mode == SHADERMODE_LIGHTSOURCE)
6047 if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6048 if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
6049 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
6050 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
6051 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
6053 // additive passes are only darkened by fog, not tinted
6054 if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
6055 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6059 if (mode == SHADERMODE_FLATCOLOR)
6061 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
6063 else if (mode == SHADERMODE_LIGHTDIRECTION)
6065 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
6066 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
6067 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
6068 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
6069 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
6070 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
6071 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
6075 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
6076 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
6077 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
6078 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
6079 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
6081 // additive passes are only darkened by fog, not tinted
6082 if (r_cg_permutation->fp_FogColor)
6084 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6085 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
6087 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6090 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
6091 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
6092 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
6093 if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);CHECKCGERROR
6094 if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);CHECKCGERROR
6095 if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
6096 if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
6097 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6098 if (r_cg_permutation->fp_NormalmapScrollBlend) cgGLSetParameter2f(r_cg_permutation->fp_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
6100 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
6101 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
6102 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
6103 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
6104 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6105 if (r_cg_permutation->fp_Color_Pants)
6107 if (rsurface.texture->pantstexture)
6108 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6110 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
6113 if (r_cg_permutation->fp_Color_Shirt)
6115 if (rsurface.texture->shirttexture)
6116 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6118 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
6121 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
6122 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
6123 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
6124 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
6125 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
6126 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
6127 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6129 // if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_texture_white );CHECKCGERROR
6130 // if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_texture_white );CHECKCGERROR
6131 // if (r_cg_permutation->fp_Texture_GammaRamps ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps , r_texture_gammaramps );CHECKCGERROR
6132 if (r_cg_permutation->fp_Texture_Normal ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal , rsurface.texture->nmaptexture );CHECKCGERROR
6133 if (r_cg_permutation->fp_Texture_Color ) CG_BindTexture(r_cg_permutation->fp_Texture_Color , rsurface.texture->basetexture );CHECKCGERROR
6134 if (r_cg_permutation->fp_Texture_Gloss ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss , rsurface.texture->glosstexture );CHECKCGERROR
6135 if (r_cg_permutation->fp_Texture_Glow ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow , rsurface.texture->glowtexture );CHECKCGERROR
6136 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture );CHECKCGERROR
6137 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );CHECKCGERROR
6138 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );CHECKCGERROR
6139 if (r_cg_permutation->fp_Texture_SecondaryGlow ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );CHECKCGERROR
6140 if (r_cg_permutation->fp_Texture_Pants ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants , rsurface.texture->pantstexture );CHECKCGERROR
6141 if (r_cg_permutation->fp_Texture_Shirt ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt , rsurface.texture->shirttexture );CHECKCGERROR
6142 if (r_cg_permutation->fp_Texture_ReflectMask ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask , rsurface.texture->reflectmasktexture );CHECKCGERROR
6143 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
6144 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture );CHECKCGERROR
6145 if (r_cg_permutation->fp_Texture_FogMask ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask , r_texture_fogattenuation );CHECKCGERROR
6146 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
6147 if (r_cg_permutation->fp_Texture_Deluxemap ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
6148 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
6149 if (rsurfacepass == RSURFPASS_BACKGROUND)
6151 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
6152 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
6153 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
6157 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
6159 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
6160 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
6161 if (r_cg_permutation->fp_Texture_ScreenDiffuse ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );CHECKCGERROR
6162 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );CHECKCGERROR
6163 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6165 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
6166 if (rsurface.rtlight)
6168 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
6169 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
6176 case RENDERPATH_GL13:
6177 case RENDERPATH_GL11:
6182 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6184 // select a permutation of the lighting shader appropriate to this
6185 // combination of texture, entity, light source, and fogging, only use the
6186 // minimum features necessary to avoid wasting rendering time in the
6187 // fragment shader on features that are not being used
6188 unsigned int permutation = 0;
6189 unsigned int mode = 0;
6190 const float *lightcolorbase = rtlight->currentcolor;
6191 float ambientscale = rtlight->ambientscale;
6192 float diffusescale = rtlight->diffusescale;
6193 float specularscale = rtlight->specularscale;
6194 // this is the location of the light in view space
6195 vec3_t viewlightorigin;
6196 // this transforms from view space (camera) to light space (cubemap)
6197 matrix4x4_t viewtolight;
6198 matrix4x4_t lighttoview;
6199 float viewtolight16f[16];
6200 float range = 1.0f / r_shadow_deferred_8bitrange.value;
6202 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6203 if (rtlight->currentcubemap != r_texture_whitecube)
6204 permutation |= SHADERPERMUTATION_CUBEFILTER;
6205 if (diffusescale > 0)
6206 permutation |= SHADERPERMUTATION_DIFFUSE;
6207 if (specularscale > 0)
6208 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6209 if (r_shadow_usingshadowmap2d)
6211 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6212 if (r_shadow_shadowmapvsdct)
6213 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6215 if (r_shadow_shadowmapsampler)
6216 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6217 if (r_shadow_shadowmappcf > 1)
6218 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6219 else if (r_shadow_shadowmappcf)
6220 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6222 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6223 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6224 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6225 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6226 switch(vid.renderpath)
6228 case RENDERPATH_D3D9:
6230 R_SetupShader_SetPermutationHLSL(mode, permutation);
6231 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6232 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6233 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
6234 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
6235 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6236 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6237 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6238 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6239 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6240 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6242 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
6243 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
6244 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
6245 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
6246 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
6247 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
6250 case RENDERPATH_D3D10:
6251 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6253 case RENDERPATH_D3D11:
6254 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6256 case RENDERPATH_GL20:
6257 R_SetupShader_SetPermutationGLSL(mode, permutation);
6258 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6259 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
6260 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);
6261 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);
6262 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);
6263 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]);
6264 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]);
6265 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));
6266 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]);
6267 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6269 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
6270 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
6271 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
6272 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
6273 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
6274 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
6276 case RENDERPATH_CGGL:
6278 R_SetupShader_SetPermutationCG(mode, permutation);
6279 if (r_cg_permutation->fp_LightPosition ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6280 if (r_cg_permutation->fp_ViewToLight ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6281 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
6282 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
6283 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
6284 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
6285 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
6286 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
6287 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
6288 if (r_cg_permutation->fp_PixelToScreenTexCoord ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6290 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
6291 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
6292 if (r_cg_permutation->fp_Texture_ScreenNormalMap ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
6293 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
6294 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
6295 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
6298 case RENDERPATH_GL13:
6299 case RENDERPATH_GL11:
6304 #define SKINFRAME_HASH 1024
6308 int loadsequence; // incremented each level change
6309 memexpandablearray_t array;
6310 skinframe_t *hash[SKINFRAME_HASH];
6313 r_skinframe_t r_skinframe;
6315 void R_SkinFrame_PrepareForPurge(void)
6317 r_skinframe.loadsequence++;
6318 // wrap it without hitting zero
6319 if (r_skinframe.loadsequence >= 200)
6320 r_skinframe.loadsequence = 1;
6323 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6327 // mark the skinframe as used for the purging code
6328 skinframe->loadsequence = r_skinframe.loadsequence;
6331 void R_SkinFrame_Purge(void)
6335 for (i = 0;i < SKINFRAME_HASH;i++)
6337 for (s = r_skinframe.hash[i];s;s = s->next)
6339 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6341 if (s->merged == s->base)
6343 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6344 R_PurgeTexture(s->stain );s->stain = NULL;
6345 R_PurgeTexture(s->merged);s->merged = NULL;
6346 R_PurgeTexture(s->base );s->base = NULL;
6347 R_PurgeTexture(s->pants );s->pants = NULL;
6348 R_PurgeTexture(s->shirt );s->shirt = NULL;
6349 R_PurgeTexture(s->nmap );s->nmap = NULL;
6350 R_PurgeTexture(s->gloss );s->gloss = NULL;
6351 R_PurgeTexture(s->glow );s->glow = NULL;
6352 R_PurgeTexture(s->fog );s->fog = NULL;
6353 R_PurgeTexture(s->reflect);s->reflect = NULL;
6354 s->loadsequence = 0;
6360 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6362 char basename[MAX_QPATH];
6364 Image_StripImageExtension(name, basename, sizeof(basename));
6366 if( last == NULL ) {
6368 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6369 item = r_skinframe.hash[hashindex];
6374 // linearly search through the hash bucket
6375 for( ; item ; item = item->next ) {
6376 if( !strcmp( item->basename, basename ) ) {
6383 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6387 char basename[MAX_QPATH];
6389 Image_StripImageExtension(name, basename, sizeof(basename));
6391 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6392 for (item = r_skinframe.hash[hashindex];item;item = item->next)
6393 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6397 rtexture_t *dyntexture;
6398 // check whether its a dynamic texture
6399 dyntexture = CL_GetDynTexture( basename );
6400 if (!add && !dyntexture)
6402 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6403 memset(item, 0, sizeof(*item));
6404 strlcpy(item->basename, basename, sizeof(item->basename));
6405 item->base = dyntexture; // either NULL or dyntexture handle
6406 item->textureflags = textureflags;
6407 item->comparewidth = comparewidth;
6408 item->compareheight = compareheight;
6409 item->comparecrc = comparecrc;
6410 item->next = r_skinframe.hash[hashindex];
6411 r_skinframe.hash[hashindex] = item;
6413 else if( item->base == NULL )
6415 rtexture_t *dyntexture;
6416 // check whether its a dynamic texture
6417 // 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]
6418 dyntexture = CL_GetDynTexture( basename );
6419 item->base = dyntexture; // either NULL or dyntexture handle
6422 R_SkinFrame_MarkUsed(item);
6426 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6428 unsigned long long avgcolor[5], wsum; \
6436 for(pix = 0; pix < cnt; ++pix) \
6439 for(comp = 0; comp < 3; ++comp) \
6441 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6444 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6446 for(comp = 0; comp < 3; ++comp) \
6447 avgcolor[comp] += getpixel * w; \
6450 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6451 avgcolor[4] += getpixel; \
6453 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6455 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6456 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6457 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6458 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6461 extern cvar_t gl_picmip;
6462 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6465 unsigned char *pixels;
6466 unsigned char *bumppixels;
6467 unsigned char *basepixels = NULL;
6468 int basepixels_width = 0;
6469 int basepixels_height = 0;
6470 skinframe_t *skinframe;
6471 rtexture_t *ddsbase = NULL;
6472 qboolean ddshasalpha = false;
6473 float ddsavgcolor[4];
6474 char basename[MAX_QPATH];
6475 int miplevel = R_PicmipForFlags(textureflags);
6476 int savemiplevel = miplevel;
6479 if (cls.state == ca_dedicated)
6482 // return an existing skinframe if already loaded
6483 // if loading of the first image fails, don't make a new skinframe as it
6484 // would cause all future lookups of this to be missing
6485 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6486 if (skinframe && skinframe->base)
6489 Image_StripImageExtension(name, basename, sizeof(basename));
6491 // check for DDS texture file first
6492 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6494 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6495 if (basepixels == NULL)
6499 // FIXME handle miplevel
6501 if (developer_loading.integer)
6502 Con_Printf("loading skin \"%s\"\n", name);
6504 // we've got some pixels to store, so really allocate this new texture now
6506 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6507 skinframe->stain = NULL;
6508 skinframe->merged = NULL;
6509 skinframe->base = NULL;
6510 skinframe->pants = NULL;
6511 skinframe->shirt = NULL;
6512 skinframe->nmap = NULL;
6513 skinframe->gloss = NULL;
6514 skinframe->glow = NULL;
6515 skinframe->fog = NULL;
6516 skinframe->reflect = NULL;
6517 skinframe->hasalpha = false;
6521 skinframe->base = ddsbase;
6522 skinframe->hasalpha = ddshasalpha;
6523 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6524 if (r_loadfog && skinframe->hasalpha)
6525 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6526 //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]);
6530 basepixels_width = image_width;
6531 basepixels_height = image_height;
6532 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);
6533 if (textureflags & TEXF_ALPHA)
6535 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6537 if (basepixels[j] < 255)
6539 skinframe->hasalpha = true;
6543 if (r_loadfog && skinframe->hasalpha)
6545 // has transparent pixels
6546 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6547 for (j = 0;j < image_width * image_height * 4;j += 4)
6552 pixels[j+3] = basepixels[j+3];
6554 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);
6558 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6559 //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]);
6560 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6561 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6562 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6563 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6568 mymiplevel = savemiplevel;
6569 if (r_loadnormalmap)
6570 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);
6571 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6573 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6574 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6575 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6576 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6579 // _norm is the name used by tenebrae and has been adopted as standard
6580 if (r_loadnormalmap && skinframe->nmap == NULL)
6582 mymiplevel = savemiplevel;
6583 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6585 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);
6589 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6591 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6592 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6593 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);
6595 Mem_Free(bumppixels);
6597 else if (r_shadow_bumpscale_basetexture.value > 0)
6599 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6600 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6601 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);
6604 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6605 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6608 // _luma is supported only for tenebrae compatibility
6609 // _glow is the preferred name
6610 mymiplevel = savemiplevel;
6611 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))))
6613 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);
6614 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6615 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6616 Mem_Free(pixels);pixels = NULL;
6619 mymiplevel = savemiplevel;
6620 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6622 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);
6623 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6624 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6629 mymiplevel = savemiplevel;
6630 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6632 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);
6633 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6634 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6639 mymiplevel = savemiplevel;
6640 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6642 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);
6643 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6644 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6649 mymiplevel = savemiplevel;
6650 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6652 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);
6653 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6654 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6660 Mem_Free(basepixels);
6665 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6666 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6669 unsigned char *temp1, *temp2;
6670 skinframe_t *skinframe;
6672 if (cls.state == ca_dedicated)
6675 // if already loaded just return it, otherwise make a new skinframe
6676 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6677 if (skinframe && skinframe->base)
6680 skinframe->stain = NULL;
6681 skinframe->merged = NULL;
6682 skinframe->base = NULL;
6683 skinframe->pants = NULL;
6684 skinframe->shirt = NULL;
6685 skinframe->nmap = NULL;
6686 skinframe->gloss = NULL;
6687 skinframe->glow = NULL;
6688 skinframe->fog = NULL;
6689 skinframe->reflect = NULL;
6690 skinframe->hasalpha = false;
6692 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6696 if (developer_loading.integer)
6697 Con_Printf("loading 32bit skin \"%s\"\n", name);
6699 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6701 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6702 temp2 = temp1 + width * height * 4;
6703 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6704 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);
6707 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6708 if (textureflags & TEXF_ALPHA)
6710 for (i = 3;i < width * height * 4;i += 4)
6712 if (skindata[i] < 255)
6714 skinframe->hasalpha = true;
6718 if (r_loadfog && skinframe->hasalpha)
6720 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6721 memcpy(fogpixels, skindata, width * height * 4);
6722 for (i = 0;i < width * height * 4;i += 4)
6723 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6724 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6725 Mem_Free(fogpixels);
6729 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6730 //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]);
6735 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6739 skinframe_t *skinframe;
6741 if (cls.state == ca_dedicated)
6744 // if already loaded just return it, otherwise make a new skinframe
6745 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6746 if (skinframe && skinframe->base)
6749 skinframe->stain = NULL;
6750 skinframe->merged = NULL;
6751 skinframe->base = NULL;
6752 skinframe->pants = NULL;
6753 skinframe->shirt = NULL;
6754 skinframe->nmap = NULL;
6755 skinframe->gloss = NULL;
6756 skinframe->glow = NULL;
6757 skinframe->fog = NULL;
6758 skinframe->reflect = NULL;
6759 skinframe->hasalpha = false;
6761 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6765 if (developer_loading.integer)
6766 Con_Printf("loading quake skin \"%s\"\n", name);
6768 // 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)
6769 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height);
6770 memcpy(skinframe->qpixels, skindata, width*height);
6771 skinframe->qwidth = width;
6772 skinframe->qheight = height;
6775 for (i = 0;i < width * height;i++)
6776 featuresmask |= palette_featureflags[skindata[i]];
6778 skinframe->hasalpha = false;
6779 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6780 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6781 skinframe->qgeneratemerged = true;
6782 skinframe->qgeneratebase = skinframe->qhascolormapping;
6783 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6785 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6786 //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]);
6791 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6795 unsigned char *skindata;
6797 if (!skinframe->qpixels)
6800 if (!skinframe->qhascolormapping)
6801 colormapped = false;
6805 if (!skinframe->qgeneratebase)
6810 if (!skinframe->qgeneratemerged)
6814 width = skinframe->qwidth;
6815 height = skinframe->qheight;
6816 skindata = skinframe->qpixels;
6818 if (skinframe->qgeneratenmap)
6820 unsigned char *temp1, *temp2;
6821 skinframe->qgeneratenmap = false;
6822 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6823 temp2 = temp1 + width * height * 4;
6824 // use either a custom palette or the quake palette
6825 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6826 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6827 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);
6831 if (skinframe->qgenerateglow)
6833 skinframe->qgenerateglow = false;
6834 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6839 skinframe->qgeneratebase = false;
6840 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);
6841 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6842 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6846 skinframe->qgeneratemerged = false;
6847 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);
6850 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6852 Mem_Free(skinframe->qpixels);
6853 skinframe->qpixels = NULL;
6857 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)
6860 skinframe_t *skinframe;
6862 if (cls.state == ca_dedicated)
6865 // if already loaded just return it, otherwise make a new skinframe
6866 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6867 if (skinframe && skinframe->base)
6870 skinframe->stain = NULL;
6871 skinframe->merged = NULL;
6872 skinframe->base = NULL;
6873 skinframe->pants = NULL;
6874 skinframe->shirt = NULL;
6875 skinframe->nmap = NULL;
6876 skinframe->gloss = NULL;
6877 skinframe->glow = NULL;
6878 skinframe->fog = NULL;
6879 skinframe->reflect = NULL;
6880 skinframe->hasalpha = false;
6882 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6886 if (developer_loading.integer)
6887 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6889 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6890 if (textureflags & TEXF_ALPHA)
6892 for (i = 0;i < width * height;i++)
6894 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6896 skinframe->hasalpha = true;
6900 if (r_loadfog && skinframe->hasalpha)
6901 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6904 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6905 //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]);
6910 skinframe_t *R_SkinFrame_LoadMissing(void)
6912 skinframe_t *skinframe;
6914 if (cls.state == ca_dedicated)
6917 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6918 skinframe->stain = NULL;
6919 skinframe->merged = NULL;
6920 skinframe->base = NULL;
6921 skinframe->pants = NULL;
6922 skinframe->shirt = NULL;
6923 skinframe->nmap = NULL;
6924 skinframe->gloss = NULL;
6925 skinframe->glow = NULL;
6926 skinframe->fog = NULL;
6927 skinframe->reflect = NULL;
6928 skinframe->hasalpha = false;
6930 skinframe->avgcolor[0] = rand() / RAND_MAX;
6931 skinframe->avgcolor[1] = rand() / RAND_MAX;
6932 skinframe->avgcolor[2] = rand() / RAND_MAX;
6933 skinframe->avgcolor[3] = 1;
6938 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6939 typedef struct suffixinfo_s
6942 qboolean flipx, flipy, flipdiagonal;
6945 static suffixinfo_t suffix[3][6] =
6948 {"px", false, false, false},
6949 {"nx", false, false, false},
6950 {"py", false, false, false},
6951 {"ny", false, false, false},
6952 {"pz", false, false, false},
6953 {"nz", false, false, false}
6956 {"posx", false, false, false},
6957 {"negx", false, false, false},
6958 {"posy", false, false, false},
6959 {"negy", false, false, false},
6960 {"posz", false, false, false},
6961 {"negz", false, false, false}
6964 {"rt", true, false, true},
6965 {"lf", false, true, true},
6966 {"ft", true, true, false},
6967 {"bk", false, false, false},
6968 {"up", true, false, true},
6969 {"dn", true, false, true}
6973 static int componentorder[4] = {0, 1, 2, 3};
6975 rtexture_t *R_LoadCubemap(const char *basename)
6977 int i, j, cubemapsize;
6978 unsigned char *cubemappixels, *image_buffer;
6979 rtexture_t *cubemaptexture;
6981 // must start 0 so the first loadimagepixels has no requested width/height
6983 cubemappixels = NULL;
6984 cubemaptexture = NULL;
6985 // keep trying different suffix groups (posx, px, rt) until one loads
6986 for (j = 0;j < 3 && !cubemappixels;j++)
6988 // load the 6 images in the suffix group
6989 for (i = 0;i < 6;i++)
6991 // generate an image name based on the base and and suffix
6992 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6994 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
6996 // an image loaded, make sure width and height are equal
6997 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6999 // if this is the first image to load successfully, allocate the cubemap memory
7000 if (!cubemappixels && image_width >= 1)
7002 cubemapsize = image_width;
7003 // note this clears to black, so unavailable sides are black
7004 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
7006 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
7008 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);
7011 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
7013 Mem_Free(image_buffer);
7017 // if a cubemap loaded, upload it
7020 if (developer_loading.integer)
7021 Con_Printf("loading cubemap \"%s\"\n", basename);
7023 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
7024 Mem_Free(cubemappixels);
7028 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
7029 if (developer_loading.integer)
7031 Con_Printf("(tried tried images ");
7032 for (j = 0;j < 3;j++)
7033 for (i = 0;i < 6;i++)
7034 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
7035 Con_Print(" and was unable to find any of them).\n");
7038 return cubemaptexture;
7041 rtexture_t *R_GetCubemap(const char *basename)
7044 for (i = 0;i < r_texture_numcubemaps;i++)
7045 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
7046 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
7047 if (i >= MAX_CUBEMAPS)
7048 return r_texture_whitecube;
7049 r_texture_numcubemaps++;
7050 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
7051 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
7052 return r_texture_cubemaps[i].texture;
7055 void R_FreeCubemaps(void)
7058 for (i = 0;i < r_texture_numcubemaps;i++)
7060 if (developer_loading.integer)
7061 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
7062 if (r_texture_cubemaps[i].texture)
7063 R_FreeTexture(r_texture_cubemaps[i].texture);
7065 r_texture_numcubemaps = 0;
7068 void R_Main_FreeViewCache(void)
7070 if (r_refdef.viewcache.entityvisible)
7071 Mem_Free(r_refdef.viewcache.entityvisible);
7072 if (r_refdef.viewcache.world_pvsbits)
7073 Mem_Free(r_refdef.viewcache.world_pvsbits);
7074 if (r_refdef.viewcache.world_leafvisible)
7075 Mem_Free(r_refdef.viewcache.world_leafvisible);
7076 if (r_refdef.viewcache.world_surfacevisible)
7077 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7078 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
7081 void R_Main_ResizeViewCache(void)
7083 int numentities = r_refdef.scene.numentities;
7084 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
7085 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
7086 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
7087 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
7088 if (r_refdef.viewcache.maxentities < numentities)
7090 r_refdef.viewcache.maxentities = numentities;
7091 if (r_refdef.viewcache.entityvisible)
7092 Mem_Free(r_refdef.viewcache.entityvisible);
7093 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
7095 if (r_refdef.viewcache.world_numclusters != numclusters)
7097 r_refdef.viewcache.world_numclusters = numclusters;
7098 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
7099 if (r_refdef.viewcache.world_pvsbits)
7100 Mem_Free(r_refdef.viewcache.world_pvsbits);
7101 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
7103 if (r_refdef.viewcache.world_numleafs != numleafs)
7105 r_refdef.viewcache.world_numleafs = numleafs;
7106 if (r_refdef.viewcache.world_leafvisible)
7107 Mem_Free(r_refdef.viewcache.world_leafvisible);
7108 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
7110 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
7112 r_refdef.viewcache.world_numsurfaces = numsurfaces;
7113 if (r_refdef.viewcache.world_surfacevisible)
7114 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7115 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
7119 extern rtexture_t *loadingscreentexture;
7120 void gl_main_start(void)
7122 loadingscreentexture = NULL;
7123 r_texture_blanknormalmap = NULL;
7124 r_texture_white = NULL;
7125 r_texture_grey128 = NULL;
7126 r_texture_black = NULL;
7127 r_texture_whitecube = NULL;
7128 r_texture_normalizationcube = NULL;
7129 r_texture_fogattenuation = NULL;
7130 r_texture_fogheighttexture = NULL;
7131 r_texture_gammaramps = NULL;
7132 r_texture_numcubemaps = 0;
7134 r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
7135 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
7137 switch(vid.renderpath)
7139 case RENDERPATH_GL20:
7140 case RENDERPATH_CGGL:
7141 case RENDERPATH_D3D9:
7142 case RENDERPATH_D3D10:
7143 case RENDERPATH_D3D11:
7144 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7145 Cvar_SetValueQuick(&gl_combine, 1);
7146 Cvar_SetValueQuick(&r_glsl, 1);
7147 r_loadnormalmap = true;
7151 case RENDERPATH_GL13:
7152 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7153 Cvar_SetValueQuick(&gl_combine, 1);
7154 Cvar_SetValueQuick(&r_glsl, 0);
7155 r_loadnormalmap = false;
7156 r_loadgloss = false;
7159 case RENDERPATH_GL11:
7160 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7161 Cvar_SetValueQuick(&gl_combine, 0);
7162 Cvar_SetValueQuick(&r_glsl, 0);
7163 r_loadnormalmap = false;
7164 r_loadgloss = false;
7170 R_FrameData_Reset();
7174 memset(r_queries, 0, sizeof(r_queries));
7176 r_qwskincache = NULL;
7177 r_qwskincache_size = 0;
7179 // set up r_skinframe loading system for textures
7180 memset(&r_skinframe, 0, sizeof(r_skinframe));
7181 r_skinframe.loadsequence = 1;
7182 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7184 r_main_texturepool = R_AllocTexturePool();
7185 R_BuildBlankTextures();
7187 if (vid.support.arb_texture_cube_map)
7190 R_BuildNormalizationCube();
7192 r_texture_fogattenuation = NULL;
7193 r_texture_fogheighttexture = NULL;
7194 r_texture_gammaramps = NULL;
7195 //r_texture_fogintensity = NULL;
7196 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7197 memset(&r_waterstate, 0, sizeof(r_waterstate));
7198 r_glsl_permutation = NULL;
7199 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7200 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7201 glslshaderstring = NULL;
7203 r_cg_permutation = NULL;
7204 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7205 Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7206 cgshaderstring = NULL;
7209 r_hlsl_permutation = NULL;
7210 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7211 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7212 hlslshaderstring = NULL;
7214 memset(&r_svbsp, 0, sizeof (r_svbsp));
7216 r_refdef.fogmasktable_density = 0;
7219 void gl_main_shutdown(void)
7222 R_FrameData_Reset();
7224 R_Main_FreeViewCache();
7226 switch(vid.renderpath)
7228 case RENDERPATH_GL11:
7229 case RENDERPATH_GL13:
7230 case RENDERPATH_GL20:
7231 case RENDERPATH_CGGL:
7233 qglDeleteQueriesARB(r_maxqueries, r_queries);
7235 case RENDERPATH_D3D9:
7236 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7238 case RENDERPATH_D3D10:
7239 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7241 case RENDERPATH_D3D11:
7242 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7248 memset(r_queries, 0, sizeof(r_queries));
7250 r_qwskincache = NULL;
7251 r_qwskincache_size = 0;
7253 // clear out the r_skinframe state
7254 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7255 memset(&r_skinframe, 0, sizeof(r_skinframe));
7258 Mem_Free(r_svbsp.nodes);
7259 memset(&r_svbsp, 0, sizeof (r_svbsp));
7260 R_FreeTexturePool(&r_main_texturepool);
7261 loadingscreentexture = NULL;
7262 r_texture_blanknormalmap = NULL;
7263 r_texture_white = NULL;
7264 r_texture_grey128 = NULL;
7265 r_texture_black = NULL;
7266 r_texture_whitecube = NULL;
7267 r_texture_normalizationcube = NULL;
7268 r_texture_fogattenuation = NULL;
7269 r_texture_fogheighttexture = NULL;
7270 r_texture_gammaramps = NULL;
7271 r_texture_numcubemaps = 0;
7272 //r_texture_fogintensity = NULL;
7273 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7274 memset(&r_waterstate, 0, sizeof(r_waterstate));
7278 extern void CL_ParseEntityLump(char *entitystring);
7279 void gl_main_newmap(void)
7281 // FIXME: move this code to client
7282 char *entities, entname[MAX_QPATH];
7284 Mem_Free(r_qwskincache);
7285 r_qwskincache = NULL;
7286 r_qwskincache_size = 0;
7289 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7290 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7292 CL_ParseEntityLump(entities);
7296 if (cl.worldmodel->brush.entities)
7297 CL_ParseEntityLump(cl.worldmodel->brush.entities);
7299 R_Main_FreeViewCache();
7301 R_FrameData_Reset();
7304 void GL_Main_Init(void)
7306 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7308 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7309 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7310 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7311 if (gamemode == GAME_NEHAHRA)
7313 Cvar_RegisterVariable (&gl_fogenable);
7314 Cvar_RegisterVariable (&gl_fogdensity);
7315 Cvar_RegisterVariable (&gl_fogred);
7316 Cvar_RegisterVariable (&gl_foggreen);
7317 Cvar_RegisterVariable (&gl_fogblue);
7318 Cvar_RegisterVariable (&gl_fogstart);
7319 Cvar_RegisterVariable (&gl_fogend);
7320 Cvar_RegisterVariable (&gl_skyclip);
7322 Cvar_RegisterVariable(&r_motionblur);
7323 Cvar_RegisterVariable(&r_motionblur_maxblur);
7324 Cvar_RegisterVariable(&r_motionblur_bmin);
7325 Cvar_RegisterVariable(&r_motionblur_vmin);
7326 Cvar_RegisterVariable(&r_motionblur_vmax);
7327 Cvar_RegisterVariable(&r_motionblur_vcoeff);
7328 Cvar_RegisterVariable(&r_motionblur_randomize);
7329 Cvar_RegisterVariable(&r_damageblur);
7330 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7331 Cvar_RegisterVariable(&r_equalize_entities_minambient);
7332 Cvar_RegisterVariable(&r_equalize_entities_by);
7333 Cvar_RegisterVariable(&r_equalize_entities_to);
7334 Cvar_RegisterVariable(&r_depthfirst);
7335 Cvar_RegisterVariable(&r_useinfinitefarclip);
7336 Cvar_RegisterVariable(&r_farclip_base);
7337 Cvar_RegisterVariable(&r_farclip_world);
7338 Cvar_RegisterVariable(&r_nearclip);
7339 Cvar_RegisterVariable(&r_showbboxes);
7340 Cvar_RegisterVariable(&r_showsurfaces);
7341 Cvar_RegisterVariable(&r_showtris);
7342 Cvar_RegisterVariable(&r_shownormals);
7343 Cvar_RegisterVariable(&r_showlighting);
7344 Cvar_RegisterVariable(&r_showshadowvolumes);
7345 Cvar_RegisterVariable(&r_showcollisionbrushes);
7346 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7347 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7348 Cvar_RegisterVariable(&r_showdisabledepthtest);
7349 Cvar_RegisterVariable(&r_drawportals);
7350 Cvar_RegisterVariable(&r_drawentities);
7351 Cvar_RegisterVariable(&r_draw2d);
7352 Cvar_RegisterVariable(&r_drawworld);
7353 Cvar_RegisterVariable(&r_cullentities_trace);
7354 Cvar_RegisterVariable(&r_cullentities_trace_samples);
7355 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7356 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7357 Cvar_RegisterVariable(&r_cullentities_trace_delay);
7358 Cvar_RegisterVariable(&r_drawviewmodel);
7359 Cvar_RegisterVariable(&r_drawexteriormodel);
7360 Cvar_RegisterVariable(&r_speeds);
7361 Cvar_RegisterVariable(&r_fullbrights);
7362 Cvar_RegisterVariable(&r_wateralpha);
7363 Cvar_RegisterVariable(&r_dynamic);
7364 Cvar_RegisterVariable(&r_fakelight);
7365 Cvar_RegisterVariable(&r_fakelight_intensity);
7366 Cvar_RegisterVariable(&r_fullbright);
7367 Cvar_RegisterVariable(&r_shadows);
7368 Cvar_RegisterVariable(&r_shadows_darken);
7369 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7370 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7371 Cvar_RegisterVariable(&r_shadows_throwdistance);
7372 Cvar_RegisterVariable(&r_shadows_throwdirection);
7373 Cvar_RegisterVariable(&r_shadows_focus);
7374 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7375 Cvar_RegisterVariable(&r_q1bsp_skymasking);
7376 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7377 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7378 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7379 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7380 Cvar_RegisterVariable(&r_fog_exp2);
7381 Cvar_RegisterVariable(&r_drawfog);
7382 Cvar_RegisterVariable(&r_transparentdepthmasking);
7383 Cvar_RegisterVariable(&r_texture_dds_load);
7384 Cvar_RegisterVariable(&r_texture_dds_save);
7385 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7386 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7387 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7388 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7389 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7390 Cvar_RegisterVariable(&r_textureunits);
7391 Cvar_RegisterVariable(&gl_combine);
7392 Cvar_RegisterVariable(&r_glsl);
7393 Cvar_RegisterVariable(&r_glsl_deluxemapping);
7394 Cvar_RegisterVariable(&r_glsl_offsetmapping);
7395 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7396 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7397 Cvar_RegisterVariable(&r_glsl_postprocess);
7398 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7399 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7400 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7401 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7402 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
7403 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
7404 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
7405 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
7407 Cvar_RegisterVariable(&r_water);
7408 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7409 Cvar_RegisterVariable(&r_water_clippingplanebias);
7410 Cvar_RegisterVariable(&r_water_refractdistort);
7411 Cvar_RegisterVariable(&r_water_reflectdistort);
7412 Cvar_RegisterVariable(&r_water_scissormode);
7413 Cvar_RegisterVariable(&r_lerpsprites);
7414 Cvar_RegisterVariable(&r_lerpmodels);
7415 Cvar_RegisterVariable(&r_lerplightstyles);
7416 Cvar_RegisterVariable(&r_waterscroll);
7417 Cvar_RegisterVariable(&r_bloom);
7418 Cvar_RegisterVariable(&r_bloom_colorscale);
7419 Cvar_RegisterVariable(&r_bloom_brighten);
7420 Cvar_RegisterVariable(&r_bloom_blur);
7421 Cvar_RegisterVariable(&r_bloom_resolution);
7422 Cvar_RegisterVariable(&r_bloom_colorexponent);
7423 Cvar_RegisterVariable(&r_bloom_colorsubtract);
7424 Cvar_RegisterVariable(&r_hdr);
7425 Cvar_RegisterVariable(&r_hdr_scenebrightness);
7426 Cvar_RegisterVariable(&r_hdr_glowintensity);
7427 Cvar_RegisterVariable(&r_hdr_range);
7428 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7429 Cvar_RegisterVariable(&developer_texturelogging);
7430 Cvar_RegisterVariable(&gl_lightmaps);
7431 Cvar_RegisterVariable(&r_test);
7432 Cvar_RegisterVariable(&r_glsl_saturation);
7433 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
7434 Cvar_RegisterVariable(&r_framedatasize);
7435 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7436 Cvar_SetValue("r_fullbrights", 0);
7437 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7439 Cvar_RegisterVariable(&r_track_sprites);
7440 Cvar_RegisterVariable(&r_track_sprites_flags);
7441 Cvar_RegisterVariable(&r_track_sprites_scalew);
7442 Cvar_RegisterVariable(&r_track_sprites_scaleh);
7443 Cvar_RegisterVariable(&r_overheadsprites_perspective);
7444 Cvar_RegisterVariable(&r_overheadsprites_pushback);
7447 extern void R_Textures_Init(void);
7448 extern void GL_Draw_Init(void);
7449 extern void GL_Main_Init(void);
7450 extern void R_Shadow_Init(void);
7451 extern void R_Sky_Init(void);
7452 extern void GL_Surf_Init(void);
7453 extern void R_Particles_Init(void);
7454 extern void R_Explosion_Init(void);
7455 extern void gl_backend_init(void);
7456 extern void Sbar_Init(void);
7457 extern void R_LightningBeams_Init(void);
7458 extern void Mod_RenderInit(void);
7459 extern void Font_Init(void);
7461 void Render_Init(void)
7474 R_LightningBeams_Init();
7483 extern char *ENGINE_EXTENSIONS;
7486 gl_renderer = (const char *)qglGetString(GL_RENDERER);
7487 gl_vendor = (const char *)qglGetString(GL_VENDOR);
7488 gl_version = (const char *)qglGetString(GL_VERSION);
7489 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7493 if (!gl_platformextensions)
7494 gl_platformextensions = "";
7496 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7497 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7498 Con_Printf("GL_VERSION: %s\n", gl_version);
7499 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7500 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7502 VID_CheckExtensions();
7504 // LordHavoc: report supported extensions
7505 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7507 // clear to black (loading plaque will be seen over this)
7508 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7511 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7515 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7517 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7520 p = r_refdef.view.frustum + i;
7525 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7529 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7533 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7537 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7541 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7545 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7549 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7553 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7561 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7565 for (i = 0;i < numplanes;i++)
7572 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7576 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7580 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7584 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7588 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7592 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7596 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7600 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7608 //==================================================================================
7610 // LordHavoc: this stores temporary data used within the same frame
7612 qboolean r_framedata_failed;
7613 static size_t r_framedata_size;
7614 static size_t r_framedata_current;
7615 static void *r_framedata_base;
7617 void R_FrameData_Reset(void)
7619 if (r_framedata_base)
7620 Mem_Free(r_framedata_base);
7621 r_framedata_base = NULL;
7622 r_framedata_size = 0;
7623 r_framedata_current = 0;
7624 r_framedata_failed = false;
7627 void R_FrameData_NewFrame(void)
7630 if (r_framedata_failed)
7631 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
7632 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7633 wantedsize = bound(65536, wantedsize, 128*1024*1024);
7634 if (r_framedata_size != wantedsize)
7636 r_framedata_size = wantedsize;
7637 if (r_framedata_base)
7638 Mem_Free(r_framedata_base);
7639 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
7641 r_framedata_current = 0;
7642 r_framedata_failed = false;
7645 void *R_FrameData_Alloc(size_t size)
7649 // align to 16 byte boundary
7650 size = (size + 15) & ~15;
7651 data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
7652 r_framedata_current += size;
7655 if (r_framedata_current > r_framedata_size)
7656 r_framedata_failed = true;
7658 // return NULL on everything after a failure
7659 if (r_framedata_failed)
7665 void *R_FrameData_Store(size_t size, void *data)
7667 void *d = R_FrameData_Alloc(size);
7669 memcpy(d, data, size);
7673 //==================================================================================
7675 // LordHavoc: animcache originally written by Echon, rewritten since then
7678 * Animation cache prevents re-generating mesh data for an animated model
7679 * multiple times in one frame for lighting, shadowing, reflections, etc.
7682 void R_AnimCache_Free(void)
7686 void R_AnimCache_ClearCache(void)
7689 entity_render_t *ent;
7691 for (i = 0;i < r_refdef.scene.numentities;i++)
7693 ent = r_refdef.scene.entities[i];
7694 ent->animcache_vertex3f = NULL;
7695 ent->animcache_normal3f = NULL;
7696 ent->animcache_svector3f = NULL;
7697 ent->animcache_tvector3f = NULL;
7698 ent->animcache_vertexposition = NULL;
7699 ent->animcache_vertexmesh = NULL;
7700 ent->animcache_vertexpositionbuffer = NULL;
7701 ent->animcache_vertexmeshbuffer = NULL;
7705 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7709 // identical memory layout, so no need to allocate...
7710 // this also provides the vertexposition structure to everything, e.g.
7711 // depth masked rendering currently uses it even if having separate
7713 // NOTE: get rid of this optimization if changing it to e.g. 4f
7714 ent->animcache_vertexposition = (r_vertexposition_t *)ent->animcache_vertex3f;
7717 // get rid of following uses of VERTEXPOSITION, change to the array:
7718 // R_DrawTextureSurfaceList_Sky if skyrendermasked
7719 // R_DrawSurface_TransparentCallback if r_transparentdepthmasking.integer
7720 // R_DrawTextureSurfaceList_DepthOnly
7721 // R_Q1BSP_DrawShadowMap
7723 switch(vid.renderpath)
7725 case RENDERPATH_GL20:
7726 case RENDERPATH_CGGL:
7727 // need the meshbuffers if !gl_mesh_separatearrays.integer
7728 if (gl_mesh_separatearrays.integer)
7731 case RENDERPATH_D3D9:
7732 case RENDERPATH_D3D10:
7733 case RENDERPATH_D3D11:
7734 // always need the meshbuffers
7736 case RENDERPATH_GL13:
7737 case RENDERPATH_GL11:
7738 // never need the meshbuffers
7742 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7743 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7745 if (!ent->animcache_vertexposition)
7746 ent->animcache_vertexposition = (r_vertexposition_t *)R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
7748 if (ent->animcache_vertexposition)
7751 for (i = 0;i < numvertices;i++)
7752 memcpy(ent->animcache_vertexposition[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7754 // TODO: upload vertex buffer?
7756 if (ent->animcache_vertexmesh)
7758 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7759 for (i = 0;i < numvertices;i++)
7760 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7761 if (ent->animcache_svector3f)
7762 for (i = 0;i < numvertices;i++)
7763 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7764 if (ent->animcache_tvector3f)
7765 for (i = 0;i < numvertices;i++)
7766 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7767 if (ent->animcache_normal3f)
7768 for (i = 0;i < numvertices;i++)
7769 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7770 // TODO: upload vertex buffer?
7774 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7776 dp_model_t *model = ent->model;
7778 // see if it's already cached this frame
7779 if (ent->animcache_vertex3f)
7781 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7782 if (wantnormals || wanttangents)
7784 if (ent->animcache_normal3f)
7785 wantnormals = false;
7786 if (ent->animcache_svector3f)
7787 wanttangents = false;
7788 if (wantnormals || wanttangents)
7790 numvertices = model->surfmesh.num_vertices;
7792 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7795 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7796 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7798 if (!r_framedata_failed)
7800 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7801 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7808 // see if this ent is worth caching
7809 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7811 // get some memory for this entity and generate mesh data
7812 numvertices = model->surfmesh.num_vertices;
7813 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7815 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7818 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7819 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7821 if (!r_framedata_failed)
7823 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7824 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7827 return !r_framedata_failed;
7830 void R_AnimCache_CacheVisibleEntities(void)
7833 qboolean wantnormals = true;
7834 qboolean wanttangents = !r_showsurfaces.integer;
7836 switch(vid.renderpath)
7838 case RENDERPATH_GL20:
7839 case RENDERPATH_CGGL:
7840 case RENDERPATH_D3D9:
7841 case RENDERPATH_D3D10:
7842 case RENDERPATH_D3D11:
7844 case RENDERPATH_GL13:
7845 case RENDERPATH_GL11:
7846 wanttangents = false;
7850 if (r_shownormals.integer)
7851 wanttangents = wantnormals = true;
7853 // TODO: thread this
7854 // NOTE: R_PrepareRTLights() also caches entities
7856 for (i = 0;i < r_refdef.scene.numentities;i++)
7857 if (r_refdef.viewcache.entityvisible[i])
7858 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7861 //==================================================================================
7863 static void R_View_UpdateEntityLighting (void)
7866 entity_render_t *ent;
7867 vec3_t tempdiffusenormal, avg;
7868 vec_t f, fa, fd, fdd;
7869 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7871 for (i = 0;i < r_refdef.scene.numentities;i++)
7873 ent = r_refdef.scene.entities[i];
7875 // skip unseen models
7876 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7880 if (ent->model && ent->model->brush.num_leafs)
7882 // TODO: use modellight for r_ambient settings on world?
7883 VectorSet(ent->modellight_ambient, 0, 0, 0);
7884 VectorSet(ent->modellight_diffuse, 0, 0, 0);
7885 VectorSet(ent->modellight_lightdir, 0, 0, 1);
7889 // fetch the lighting from the worldmodel data
7890 VectorClear(ent->modellight_ambient);
7891 VectorClear(ent->modellight_diffuse);
7892 VectorClear(tempdiffusenormal);
7893 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7896 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7898 // complete lightning for lit sprites
7899 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
7900 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
7902 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
7903 org[2] = org[2] + r_overheadsprites_pushback.value;
7904 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, ent->modellight_lightdir, org, true, true);
7907 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7909 if(ent->flags & RENDER_EQUALIZE)
7911 // first fix up ambient lighting...
7912 if(r_equalize_entities_minambient.value > 0)
7914 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7917 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7918 if(fa < r_equalize_entities_minambient.value * fd)
7921 // fa'/fd' = minambient
7922 // fa'+0.25*fd' = fa+0.25*fd
7924 // fa' = fd' * minambient
7925 // fd'*(0.25+minambient) = fa+0.25*fd
7927 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7928 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7930 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7931 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
7932 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7933 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7938 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7940 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
7941 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
7944 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
7945 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
7946 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7952 VectorSet(ent->modellight_ambient, 1, 1, 1);
7954 // move the light direction into modelspace coordinates for lighting code
7955 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7956 if(VectorLength2(ent->modellight_lightdir) == 0)
7957 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7958 VectorNormalize(ent->modellight_lightdir);
7962 #define MAX_LINEOFSIGHTTRACES 64
7964 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7967 vec3_t boxmins, boxmaxs;
7970 dp_model_t *model = r_refdef.scene.worldmodel;
7972 if (!model || !model->brush.TraceLineOfSight)
7975 // expand the box a little
7976 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7977 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7978 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7979 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7980 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7981 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7983 // return true if eye is inside enlarged box
7984 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7988 VectorCopy(eye, start);
7989 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7990 if (model->brush.TraceLineOfSight(model, start, end))
7993 // try various random positions
7994 for (i = 0;i < numsamples;i++)
7996 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7997 if (model->brush.TraceLineOfSight(model, start, end))
8005 static void R_View_UpdateEntityVisible (void)
8010 entity_render_t *ent;
8012 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8013 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8014 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
8015 : RENDER_EXTERIORMODEL;
8016 if (!r_drawviewmodel.integer)
8017 renderimask |= RENDER_VIEWMODEL;
8018 if (!r_drawexteriormodel.integer)
8019 renderimask |= RENDER_EXTERIORMODEL;
8020 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
8022 // worldmodel can check visibility
8023 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
8024 for (i = 0;i < r_refdef.scene.numentities;i++)
8026 ent = r_refdef.scene.entities[i];
8027 if (!(ent->flags & renderimask))
8028 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)))
8029 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))
8030 r_refdef.viewcache.entityvisible[i] = true;
8032 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
8033 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
8035 for (i = 0;i < r_refdef.scene.numentities;i++)
8037 ent = r_refdef.scene.entities[i];
8038 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
8040 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
8042 continue; // temp entities do pvs only
8043 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
8044 ent->last_trace_visibility = realtime;
8045 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
8046 r_refdef.viewcache.entityvisible[i] = 0;
8053 // no worldmodel or it can't check visibility
8054 for (i = 0;i < r_refdef.scene.numentities;i++)
8056 ent = r_refdef.scene.entities[i];
8057 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));
8062 /// only used if skyrendermasked, and normally returns false
8063 int R_DrawBrushModelsSky (void)
8066 entity_render_t *ent;
8069 for (i = 0;i < r_refdef.scene.numentities;i++)
8071 if (!r_refdef.viewcache.entityvisible[i])
8073 ent = r_refdef.scene.entities[i];
8074 if (!ent->model || !ent->model->DrawSky)
8076 ent->model->DrawSky(ent);
8082 static void R_DrawNoModel(entity_render_t *ent);
8083 static void R_DrawModels(void)
8086 entity_render_t *ent;
8088 for (i = 0;i < r_refdef.scene.numentities;i++)
8090 if (!r_refdef.viewcache.entityvisible[i])
8092 ent = r_refdef.scene.entities[i];
8093 r_refdef.stats.entities++;
8094 if (ent->model && ent->model->Draw != NULL)
8095 ent->model->Draw(ent);
8101 static void R_DrawModelsDepth(void)
8104 entity_render_t *ent;
8106 for (i = 0;i < r_refdef.scene.numentities;i++)
8108 if (!r_refdef.viewcache.entityvisible[i])
8110 ent = r_refdef.scene.entities[i];
8111 if (ent->model && ent->model->DrawDepth != NULL)
8112 ent->model->DrawDepth(ent);
8116 static void R_DrawModelsDebug(void)
8119 entity_render_t *ent;
8121 for (i = 0;i < r_refdef.scene.numentities;i++)
8123 if (!r_refdef.viewcache.entityvisible[i])
8125 ent = r_refdef.scene.entities[i];
8126 if (ent->model && ent->model->DrawDebug != NULL)
8127 ent->model->DrawDebug(ent);
8131 static void R_DrawModelsAddWaterPlanes(void)
8134 entity_render_t *ent;
8136 for (i = 0;i < r_refdef.scene.numentities;i++)
8138 if (!r_refdef.viewcache.entityvisible[i])
8140 ent = r_refdef.scene.entities[i];
8141 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
8142 ent->model->DrawAddWaterPlanes(ent);
8146 static void R_View_SetFrustum(const int *scissor)
8149 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
8150 vec3_t forward, left, up, origin, v;
8154 // flipped x coordinates (because x points left here)
8155 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8156 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8158 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
8159 switch(vid.renderpath)
8161 case RENDERPATH_D3D9:
8162 case RENDERPATH_D3D10:
8163 case RENDERPATH_D3D11:
8164 // non-flipped y coordinates
8165 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8166 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8168 case RENDERPATH_GL11:
8169 case RENDERPATH_GL13:
8170 case RENDERPATH_GL20:
8171 case RENDERPATH_CGGL:
8172 // non-flipped y coordinates
8173 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8174 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8179 // we can't trust r_refdef.view.forward and friends in reflected scenes
8180 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
8183 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
8184 r_refdef.view.frustum[0].normal[1] = 0 - 0;
8185 r_refdef.view.frustum[0].normal[2] = -1 - 0;
8186 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
8187 r_refdef.view.frustum[1].normal[1] = 0 + 0;
8188 r_refdef.view.frustum[1].normal[2] = -1 + 0;
8189 r_refdef.view.frustum[2].normal[0] = 0 - 0;
8190 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
8191 r_refdef.view.frustum[2].normal[2] = -1 - 0;
8192 r_refdef.view.frustum[3].normal[0] = 0 + 0;
8193 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
8194 r_refdef.view.frustum[3].normal[2] = -1 + 0;
8198 zNear = r_refdef.nearclip;
8199 nudge = 1.0 - 1.0 / (1<<23);
8200 r_refdef.view.frustum[4].normal[0] = 0 - 0;
8201 r_refdef.view.frustum[4].normal[1] = 0 - 0;
8202 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
8203 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
8204 r_refdef.view.frustum[5].normal[0] = 0 + 0;
8205 r_refdef.view.frustum[5].normal[1] = 0 + 0;
8206 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
8207 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
8213 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8214 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8215 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8216 r_refdef.view.frustum[0].dist = m[15] - m[12];
8218 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8219 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8220 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8221 r_refdef.view.frustum[1].dist = m[15] + m[12];
8223 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8224 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8225 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8226 r_refdef.view.frustum[2].dist = m[15] - m[13];
8228 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8229 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8230 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8231 r_refdef.view.frustum[3].dist = m[15] + m[13];
8233 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8234 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8235 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8236 r_refdef.view.frustum[4].dist = m[15] - m[14];
8238 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8239 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8240 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8241 r_refdef.view.frustum[5].dist = m[15] + m[14];
8244 if (r_refdef.view.useperspective)
8246 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8247 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]);
8248 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]);
8249 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]);
8250 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]);
8252 // then the normals from the corners relative to origin
8253 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
8254 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
8255 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
8256 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
8258 // in a NORMAL view, forward cross left == up
8259 // in a REFLECTED view, forward cross left == down
8260 // so our cross products above need to be adjusted for a left handed coordinate system
8261 CrossProduct(forward, left, v);
8262 if(DotProduct(v, up) < 0)
8264 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
8265 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
8266 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
8267 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
8270 // Leaving those out was a mistake, those were in the old code, and they
8271 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8272 // I couldn't reproduce it after adding those normalizations. --blub
8273 VectorNormalize(r_refdef.view.frustum[0].normal);
8274 VectorNormalize(r_refdef.view.frustum[1].normal);
8275 VectorNormalize(r_refdef.view.frustum[2].normal);
8276 VectorNormalize(r_refdef.view.frustum[3].normal);
8278 // make the corners absolute
8279 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
8280 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
8281 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
8282 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
8285 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8287 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8288 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8289 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8290 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8291 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8295 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8296 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8297 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8298 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8299 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8300 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8301 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8302 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8303 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8304 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8306 r_refdef.view.numfrustumplanes = 5;
8308 if (r_refdef.view.useclipplane)
8310 r_refdef.view.numfrustumplanes = 6;
8311 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8314 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8315 PlaneClassify(r_refdef.view.frustum + i);
8317 // LordHavoc: note to all quake engine coders, Quake had a special case
8318 // for 90 degrees which assumed a square view (wrong), so I removed it,
8319 // Quake2 has it disabled as well.
8321 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8322 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8323 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8324 //PlaneClassify(&frustum[0]);
8326 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8327 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8328 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8329 //PlaneClassify(&frustum[1]);
8331 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8332 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8333 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8334 //PlaneClassify(&frustum[2]);
8336 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8337 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8338 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8339 //PlaneClassify(&frustum[3]);
8342 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8343 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8344 //PlaneClassify(&frustum[4]);
8347 void R_View_UpdateWithScissor(const int *myscissor)
8349 R_Main_ResizeViewCache();
8350 R_View_SetFrustum(myscissor);
8351 R_View_WorldVisibility(r_refdef.view.useclipplane);
8352 R_View_UpdateEntityVisible();
8353 R_View_UpdateEntityLighting();
8356 void R_View_Update(void)
8358 R_Main_ResizeViewCache();
8359 R_View_SetFrustum(NULL);
8360 R_View_WorldVisibility(r_refdef.view.useclipplane);
8361 R_View_UpdateEntityVisible();
8362 R_View_UpdateEntityLighting();
8365 void R_SetupView(qboolean allowwaterclippingplane)
8367 const float *customclipplane = NULL;
8369 if (r_refdef.view.useclipplane && allowwaterclippingplane)
8371 // LordHavoc: couldn't figure out how to make this approach the
8372 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8373 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8374 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8375 dist = r_refdef.view.clipplane.dist;
8376 plane[0] = r_refdef.view.clipplane.normal[0];
8377 plane[1] = r_refdef.view.clipplane.normal[1];
8378 plane[2] = r_refdef.view.clipplane.normal[2];
8380 customclipplane = plane;
8383 if (!r_refdef.view.useperspective)
8384 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);
8385 else if (vid.stencil && r_useinfinitefarclip.integer)
8386 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);
8388 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);
8389 R_SetViewport(&r_refdef.view.viewport);
8392 void R_EntityMatrix(const matrix4x4_t *matrix)
8394 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8396 gl_modelmatrixchanged = false;
8397 gl_modelmatrix = *matrix;
8398 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8399 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8400 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8401 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8403 switch(vid.renderpath)
8405 case RENDERPATH_D3D9:
8407 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8408 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8411 case RENDERPATH_D3D10:
8412 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8414 case RENDERPATH_D3D11:
8415 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8417 case RENDERPATH_GL20:
8418 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8419 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8420 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8422 case RENDERPATH_CGGL:
8425 if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8426 if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8427 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8430 case RENDERPATH_GL13:
8431 case RENDERPATH_GL11:
8432 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8438 void R_ResetViewRendering2D(void)
8440 r_viewport_t viewport;
8443 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8444 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);
8445 R_SetViewport(&viewport);
8446 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8447 GL_Color(1, 1, 1, 1);
8448 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8449 GL_BlendFunc(GL_ONE, GL_ZERO);
8450 GL_AlphaTest(false);
8451 GL_ScissorTest(false);
8452 GL_DepthMask(false);
8453 GL_DepthRange(0, 1);
8454 GL_DepthTest(false);
8455 GL_DepthFunc(GL_LEQUAL);
8456 R_EntityMatrix(&identitymatrix);
8457 R_Mesh_ResetTextureState();
8458 GL_PolygonOffset(0, 0);
8459 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8460 switch(vid.renderpath)
8462 case RENDERPATH_GL11:
8463 case RENDERPATH_GL13:
8464 case RENDERPATH_GL20:
8465 case RENDERPATH_CGGL:
8466 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8468 case RENDERPATH_D3D9:
8469 case RENDERPATH_D3D10:
8470 case RENDERPATH_D3D11:
8473 GL_CullFace(GL_NONE);
8476 void R_ResetViewRendering3D(void)
8481 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8482 GL_Color(1, 1, 1, 1);
8483 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8484 GL_BlendFunc(GL_ONE, GL_ZERO);
8485 GL_AlphaTest(false);
8486 GL_ScissorTest(true);
8488 GL_DepthRange(0, 1);
8490 GL_DepthFunc(GL_LEQUAL);
8491 R_EntityMatrix(&identitymatrix);
8492 R_Mesh_ResetTextureState();
8493 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8494 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8495 switch(vid.renderpath)
8497 case RENDERPATH_GL11:
8498 case RENDERPATH_GL13:
8499 case RENDERPATH_GL20:
8500 case RENDERPATH_CGGL:
8501 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8503 case RENDERPATH_D3D9:
8504 case RENDERPATH_D3D10:
8505 case RENDERPATH_D3D11:
8508 GL_CullFace(r_refdef.view.cullface_back);
8513 R_RenderView_UpdateViewVectors
8516 static void R_RenderView_UpdateViewVectors(void)
8518 // break apart the view matrix into vectors for various purposes
8519 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8520 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8521 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8522 VectorNegate(r_refdef.view.left, r_refdef.view.right);
8523 // make an inverted copy of the view matrix for tracking sprites
8524 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8527 void R_RenderScene(void);
8528 void R_RenderWaterPlanes(void);
8530 static void R_Water_StartFrame(void)
8533 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8534 r_waterstate_waterplane_t *p;
8536 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8539 switch(vid.renderpath)
8541 case RENDERPATH_GL20:
8542 case RENDERPATH_CGGL:
8543 case RENDERPATH_D3D9:
8544 case RENDERPATH_D3D10:
8545 case RENDERPATH_D3D11:
8547 case RENDERPATH_GL13:
8548 case RENDERPATH_GL11:
8552 // set waterwidth and waterheight to the water resolution that will be
8553 // used (often less than the screen resolution for faster rendering)
8554 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8555 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8557 // calculate desired texture sizes
8558 // can't use water if the card does not support the texture size
8559 if (!r_water.integer || r_showsurfaces.integer)
8560 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8561 else if (vid.support.arb_texture_non_power_of_two)
8563 texturewidth = waterwidth;
8564 textureheight = waterheight;
8565 camerawidth = waterwidth;
8566 cameraheight = waterheight;
8570 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
8571 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
8572 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
8573 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
8576 // allocate textures as needed
8577 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8579 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8580 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8582 if (p->texture_refraction)
8583 R_FreeTexture(p->texture_refraction);
8584 p->texture_refraction = NULL;
8585 if (p->texture_reflection)
8586 R_FreeTexture(p->texture_reflection);
8587 p->texture_reflection = NULL;
8588 if (p->texture_camera)
8589 R_FreeTexture(p->texture_camera);
8590 p->texture_camera = NULL;
8592 memset(&r_waterstate, 0, sizeof(r_waterstate));
8593 r_waterstate.texturewidth = texturewidth;
8594 r_waterstate.textureheight = textureheight;
8595 r_waterstate.camerawidth = camerawidth;
8596 r_waterstate.cameraheight = cameraheight;
8599 if (r_waterstate.texturewidth)
8601 r_waterstate.enabled = true;
8603 // when doing a reduced render (HDR) we want to use a smaller area
8604 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8605 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8607 // set up variables that will be used in shader setup
8608 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8609 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8610 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8611 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8614 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8615 r_waterstate.numwaterplanes = 0;
8618 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8620 int triangleindex, planeindex;
8626 r_waterstate_waterplane_t *p;
8627 texture_t *t = R_GetCurrentTexture(surface->texture);
8629 // just use the first triangle with a valid normal for any decisions
8630 VectorClear(normal);
8631 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8633 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8634 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8635 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8636 TriangleNormal(vert[0], vert[1], vert[2], normal);
8637 if (VectorLength2(normal) >= 0.001)
8641 VectorCopy(normal, plane.normal);
8642 VectorNormalize(plane.normal);
8643 plane.dist = DotProduct(vert[0], plane.normal);
8644 PlaneClassify(&plane);
8645 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8647 // skip backfaces (except if nocullface is set)
8648 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8650 VectorNegate(plane.normal, plane.normal);
8652 PlaneClassify(&plane);
8656 // find a matching plane if there is one
8657 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8658 if(p->camera_entity == t->camera_entity)
8659 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8661 if (planeindex >= r_waterstate.maxwaterplanes)
8662 return; // nothing we can do, out of planes
8664 // if this triangle does not fit any known plane rendered this frame, add one
8665 if (planeindex >= r_waterstate.numwaterplanes)
8667 // store the new plane
8668 r_waterstate.numwaterplanes++;
8670 // clear materialflags and pvs
8671 p->materialflags = 0;
8672 p->pvsvalid = false;
8673 p->camera_entity = t->camera_entity;
8674 VectorCopy(surface->mins, p->mins);
8675 VectorCopy(surface->maxs, p->maxs);
8680 p->mins[0] = min(p->mins[0], surface->mins[0]);
8681 p->mins[1] = min(p->mins[1], surface->mins[1]);
8682 p->mins[2] = min(p->mins[2], surface->mins[2]);
8683 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8684 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8685 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8687 // merge this surface's materialflags into the waterplane
8688 p->materialflags |= t->currentmaterialflags;
8689 if(!(p->materialflags & MATERIALFLAG_CAMERA))
8691 // merge this surface's PVS into the waterplane
8692 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8693 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8694 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8696 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8702 static void R_Water_ProcessPlanes(void)
8705 r_refdef_view_t originalview;
8706 r_refdef_view_t myview;
8708 r_waterstate_waterplane_t *p;
8711 originalview = r_refdef.view;
8713 // make sure enough textures are allocated
8714 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8716 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8718 if (!p->texture_refraction)
8719 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);
8720 if (!p->texture_refraction)
8723 else if (p->materialflags & MATERIALFLAG_CAMERA)
8725 if (!p->texture_camera)
8726 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);
8727 if (!p->texture_camera)
8731 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8733 if (!p->texture_reflection)
8734 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);
8735 if (!p->texture_reflection)
8741 r_refdef.view = originalview;
8742 r_refdef.view.showdebug = false;
8743 r_refdef.view.width = r_waterstate.waterwidth;
8744 r_refdef.view.height = r_waterstate.waterheight;
8745 r_refdef.view.useclipplane = true;
8746 myview = r_refdef.view;
8747 r_waterstate.renderingscene = true;
8748 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8750 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8752 r_refdef.view = myview;
8753 if(r_water_scissormode.integer)
8756 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8757 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8760 // render reflected scene and copy into texture
8761 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8762 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8763 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8764 r_refdef.view.clipplane = p->plane;
8766 // reverse the cullface settings for this render
8767 r_refdef.view.cullface_front = GL_FRONT;
8768 r_refdef.view.cullface_back = GL_BACK;
8769 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8771 r_refdef.view.usecustompvs = true;
8773 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8775 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8778 R_ResetViewRendering3D();
8779 R_ClearScreen(r_refdef.fogenabled);
8780 if(r_water_scissormode.integer & 2)
8781 R_View_UpdateWithScissor(myscissor);
8784 if(r_water_scissormode.integer & 1)
8785 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8788 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);
8791 // render the normal view scene and copy into texture
8792 // (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)
8793 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8795 r_refdef.view = myview;
8796 if(r_water_scissormode.integer)
8799 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8800 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8803 r_waterstate.renderingrefraction = true;
8805 r_refdef.view.clipplane = p->plane;
8806 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8807 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8809 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8811 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8812 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8813 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8814 R_RenderView_UpdateViewVectors();
8815 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8817 r_refdef.view.usecustompvs = true;
8818 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);
8822 PlaneClassify(&r_refdef.view.clipplane);
8824 R_ResetViewRendering3D();
8825 R_ClearScreen(r_refdef.fogenabled);
8826 if(r_water_scissormode.integer & 2)
8827 R_View_UpdateWithScissor(myscissor);
8830 if(r_water_scissormode.integer & 1)
8831 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8834 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);
8835 r_waterstate.renderingrefraction = false;
8837 else if (p->materialflags & MATERIALFLAG_CAMERA)
8839 r_refdef.view = myview;
8841 r_refdef.view.clipplane = p->plane;
8842 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8843 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8845 r_refdef.view.width = r_waterstate.camerawidth;
8846 r_refdef.view.height = r_waterstate.cameraheight;
8847 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8848 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8850 if(p->camera_entity)
8852 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8853 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8856 // note: all of the view is used for displaying... so
8857 // there is no use in scissoring
8859 // reverse the cullface settings for this render
8860 r_refdef.view.cullface_front = GL_FRONT;
8861 r_refdef.view.cullface_back = GL_BACK;
8862 // also reverse the view matrix
8863 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
8864 R_RenderView_UpdateViewVectors();
8865 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8867 r_refdef.view.usecustompvs = true;
8868 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);
8871 // camera needs no clipplane
8872 r_refdef.view.useclipplane = false;
8874 PlaneClassify(&r_refdef.view.clipplane);
8876 R_ResetViewRendering3D();
8877 R_ClearScreen(r_refdef.fogenabled);
8881 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);
8882 r_waterstate.renderingrefraction = false;
8886 r_waterstate.renderingscene = false;
8887 r_refdef.view = originalview;
8888 R_ResetViewRendering3D();
8889 R_ClearScreen(r_refdef.fogenabled);
8893 r_refdef.view = originalview;
8894 r_waterstate.renderingscene = false;
8895 Cvar_SetValueQuick(&r_water, 0);
8896 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
8900 void R_Bloom_StartFrame(void)
8902 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8904 switch(vid.renderpath)
8906 case RENDERPATH_GL20:
8907 case RENDERPATH_CGGL:
8908 case RENDERPATH_D3D9:
8909 case RENDERPATH_D3D10:
8910 case RENDERPATH_D3D11:
8912 case RENDERPATH_GL13:
8913 case RENDERPATH_GL11:
8917 // set bloomwidth and bloomheight to the bloom resolution that will be
8918 // used (often less than the screen resolution for faster rendering)
8919 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8920 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8921 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8922 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8923 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8925 // calculate desired texture sizes
8926 if (vid.support.arb_texture_non_power_of_two)
8928 screentexturewidth = r_refdef.view.width;
8929 screentextureheight = r_refdef.view.height;
8930 bloomtexturewidth = r_bloomstate.bloomwidth;
8931 bloomtextureheight = r_bloomstate.bloomheight;
8935 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
8936 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
8937 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
8938 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
8941 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))
8943 Cvar_SetValueQuick(&r_hdr, 0);
8944 Cvar_SetValueQuick(&r_bloom, 0);
8945 Cvar_SetValueQuick(&r_motionblur, 0);
8946 Cvar_SetValueQuick(&r_damageblur, 0);
8949 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)))
8950 screentexturewidth = screentextureheight = 0;
8951 if (!r_hdr.integer && !r_bloom.integer)
8952 bloomtexturewidth = bloomtextureheight = 0;
8954 // allocate textures as needed
8955 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8957 if (r_bloomstate.texture_screen)
8958 R_FreeTexture(r_bloomstate.texture_screen);
8959 r_bloomstate.texture_screen = NULL;
8960 r_bloomstate.screentexturewidth = screentexturewidth;
8961 r_bloomstate.screentextureheight = screentextureheight;
8962 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8963 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);
8965 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8967 if (r_bloomstate.texture_bloom)
8968 R_FreeTexture(r_bloomstate.texture_bloom);
8969 r_bloomstate.texture_bloom = NULL;
8970 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8971 r_bloomstate.bloomtextureheight = bloomtextureheight;
8972 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8973 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);
8976 // when doing a reduced render (HDR) we want to use a smaller area
8977 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8978 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8979 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8980 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8981 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8983 // set up a texcoord array for the full resolution screen image
8984 // (we have to keep this around to copy back during final render)
8985 r_bloomstate.screentexcoord2f[0] = 0;
8986 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
8987 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
8988 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
8989 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
8990 r_bloomstate.screentexcoord2f[5] = 0;
8991 r_bloomstate.screentexcoord2f[6] = 0;
8992 r_bloomstate.screentexcoord2f[7] = 0;
8994 // set up a texcoord array for the reduced resolution bloom image
8995 // (which will be additive blended over the screen image)
8996 r_bloomstate.bloomtexcoord2f[0] = 0;
8997 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8998 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8999 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9000 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9001 r_bloomstate.bloomtexcoord2f[5] = 0;
9002 r_bloomstate.bloomtexcoord2f[6] = 0;
9003 r_bloomstate.bloomtexcoord2f[7] = 0;
9005 switch(vid.renderpath)
9007 case RENDERPATH_GL11:
9008 case RENDERPATH_GL13:
9009 case RENDERPATH_GL20:
9010 case RENDERPATH_CGGL:
9012 case RENDERPATH_D3D9:
9013 case RENDERPATH_D3D10:
9014 case RENDERPATH_D3D11:
9017 for (i = 0;i < 4;i++)
9019 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
9020 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
9021 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
9022 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
9028 if (r_hdr.integer || r_bloom.integer)
9030 r_bloomstate.enabled = true;
9031 r_bloomstate.hdr = r_hdr.integer != 0;
9034 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);
9037 void R_Bloom_CopyBloomTexture(float colorscale)
9039 r_refdef.stats.bloom++;
9041 // scale down screen texture to the bloom texture size
9043 R_SetViewport(&r_bloomstate.viewport);
9044 GL_BlendFunc(GL_ONE, GL_ZERO);
9045 GL_Color(colorscale, colorscale, colorscale, 1);
9046 // 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...
9047 switch(vid.renderpath)
9049 case RENDERPATH_GL11:
9050 case RENDERPATH_GL13:
9051 case RENDERPATH_GL20:
9052 case RENDERPATH_CGGL:
9053 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9055 case RENDERPATH_D3D9:
9056 case RENDERPATH_D3D10:
9057 case RENDERPATH_D3D11:
9058 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9061 // TODO: do boxfilter scale-down in shader?
9062 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9063 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9064 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9066 // we now have a bloom image in the framebuffer
9067 // copy it into the bloom image texture for later processing
9068 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);
9069 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9072 void R_Bloom_CopyHDRTexture(void)
9074 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);
9075 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9078 void R_Bloom_MakeTexture(void)
9081 float xoffset, yoffset, r, brighten;
9083 r_refdef.stats.bloom++;
9085 R_ResetViewRendering2D();
9087 // we have a bloom image in the framebuffer
9089 R_SetViewport(&r_bloomstate.viewport);
9091 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
9094 r = bound(0, r_bloom_colorexponent.value / x, 1);
9095 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9097 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
9098 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9099 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9100 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9102 // copy the vertically blurred bloom view to a texture
9103 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);
9104 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9107 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
9108 brighten = r_bloom_brighten.value;
9110 brighten *= r_hdr_range.value;
9111 brighten = sqrt(brighten);
9113 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
9114 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9116 for (dir = 0;dir < 2;dir++)
9118 // blend on at multiple vertical offsets to achieve a vertical blur
9119 // TODO: do offset blends using GLSL
9120 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
9121 GL_BlendFunc(GL_ONE, GL_ZERO);
9122 for (x = -range;x <= range;x++)
9124 if (!dir){xoffset = 0;yoffset = x;}
9125 else {xoffset = x;yoffset = 0;}
9126 xoffset /= (float)r_bloomstate.bloomtexturewidth;
9127 yoffset /= (float)r_bloomstate.bloomtextureheight;
9128 // compute a texcoord array with the specified x and y offset
9129 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
9130 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9131 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9132 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9133 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9134 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
9135 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
9136 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
9137 // this r value looks like a 'dot' particle, fading sharply to
9138 // black at the edges
9139 // (probably not realistic but looks good enough)
9140 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
9141 //r = brighten/(range*2+1);
9142 r = brighten / (range * 2 + 1);
9144 r *= (1 - x*x/(float)(range*range));
9145 GL_Color(r, r, r, 1);
9146 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
9147 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9148 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9149 GL_BlendFunc(GL_ONE, GL_ONE);
9152 // copy the vertically blurred bloom view to a texture
9153 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);
9154 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9158 void R_HDR_RenderBloomTexture(void)
9160 int oldwidth, oldheight;
9161 float oldcolorscale;
9163 oldcolorscale = r_refdef.view.colorscale;
9164 oldwidth = r_refdef.view.width;
9165 oldheight = r_refdef.view.height;
9166 r_refdef.view.width = r_bloomstate.bloomwidth;
9167 r_refdef.view.height = r_bloomstate.bloomheight;
9169 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
9170 // TODO: add exposure compensation features
9171 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
9173 r_refdef.view.showdebug = false;
9174 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
9176 R_ResetViewRendering3D();
9178 R_ClearScreen(r_refdef.fogenabled);
9179 if (r_timereport_active)
9180 R_TimeReport("HDRclear");
9183 if (r_timereport_active)
9184 R_TimeReport("visibility");
9186 // only do secondary renders with HDR if r_hdr is 2 or higher
9187 r_waterstate.numwaterplanes = 0;
9188 if (r_waterstate.enabled && r_hdr.integer >= 2)
9189 R_RenderWaterPlanes();
9191 r_refdef.view.showdebug = true;
9193 r_waterstate.numwaterplanes = 0;
9195 R_ResetViewRendering2D();
9197 R_Bloom_CopyHDRTexture();
9198 R_Bloom_MakeTexture();
9200 // restore the view settings
9201 r_refdef.view.width = oldwidth;
9202 r_refdef.view.height = oldheight;
9203 r_refdef.view.colorscale = oldcolorscale;
9205 R_ResetViewRendering3D();
9207 R_ClearScreen(r_refdef.fogenabled);
9208 if (r_timereport_active)
9209 R_TimeReport("viewclear");
9212 static void R_BlendView(void)
9214 unsigned int permutation;
9215 float uservecs[4][4];
9217 switch (vid.renderpath)
9219 case RENDERPATH_GL20:
9220 case RENDERPATH_CGGL:
9221 case RENDERPATH_D3D9:
9222 case RENDERPATH_D3D10:
9223 case RENDERPATH_D3D11:
9225 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
9226 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
9227 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
9228 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
9229 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
9231 if (r_bloomstate.texture_screen)
9233 // make sure the buffer is available
9234 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
9236 R_ResetViewRendering2D();
9238 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
9240 // declare variables
9242 static float avgspeed;
9244 speed = VectorLength(cl.movement_velocity);
9246 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
9247 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
9249 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
9250 speed = bound(0, speed, 1);
9251 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
9253 // calculate values into a standard alpha
9254 cl.motionbluralpha = 1 - exp(-
9256 (r_motionblur.value * speed / 80)
9258 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
9261 max(0.0001, cl.time - cl.oldtime) // fps independent
9264 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
9265 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
9267 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
9269 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9270 GL_Color(1, 1, 1, cl.motionbluralpha);
9271 switch(vid.renderpath)
9273 case RENDERPATH_GL11:
9274 case RENDERPATH_GL13:
9275 case RENDERPATH_GL20:
9276 case RENDERPATH_CGGL:
9277 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9279 case RENDERPATH_D3D9:
9280 case RENDERPATH_D3D10:
9281 case RENDERPATH_D3D11:
9282 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9285 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9286 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9287 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9291 // copy view into the screen texture
9292 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);
9293 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9295 else if (!r_bloomstate.texture_bloom)
9297 // we may still have to do view tint...
9298 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9300 // apply a color tint to the whole view
9301 R_ResetViewRendering2D();
9302 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9303 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9304 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9305 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9306 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9308 break; // no screen processing, no bloom, skip it
9311 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9313 // render simple bloom effect
9314 // copy the screen and shrink it and darken it for the bloom process
9315 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9316 // make the bloom texture
9317 R_Bloom_MakeTexture();
9320 #if _MSC_VER >= 1400
9321 #define sscanf sscanf_s
9323 memset(uservecs, 0, sizeof(uservecs));
9324 if (r_glsl_postprocess_uservec1_enable.integer)
9325 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9326 if (r_glsl_postprocess_uservec2_enable.integer)
9327 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9328 if (r_glsl_postprocess_uservec3_enable.integer)
9329 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9330 if (r_glsl_postprocess_uservec4_enable.integer)
9331 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9333 R_ResetViewRendering2D();
9334 GL_Color(1, 1, 1, 1);
9335 GL_BlendFunc(GL_ONE, GL_ZERO);
9337 switch(vid.renderpath)
9339 case RENDERPATH_GL20:
9340 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9341 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9342 if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
9343 if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
9344 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
9345 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]);
9346 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9347 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]);
9348 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]);
9349 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]);
9350 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]);
9351 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
9352 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9353 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);
9355 case RENDERPATH_CGGL:
9357 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9358 R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9359 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_bloomstate.texture_screen);CHECKCGERROR
9360 if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_bloomstate.texture_bloom );CHECKCGERROR
9361 if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps );CHECKCGERROR
9362 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
9363 if (r_cg_permutation->fp_PixelSize ) cgGLSetParameter2f( r_cg_permutation->fp_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9364 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
9365 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
9366 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
9367 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
9368 if (r_cg_permutation->fp_Saturation ) cgGLSetParameter1f( r_cg_permutation->fp_Saturation , r_glsl_saturation.value);CHECKCGERROR
9369 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9370 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);
9373 case RENDERPATH_D3D9:
9375 // 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...
9376 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9377 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9378 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
9379 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
9380 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
9381 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9382 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9383 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9384 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9385 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9386 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9387 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
9388 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9389 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9392 case RENDERPATH_D3D10:
9393 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9395 case RENDERPATH_D3D11:
9396 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9401 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9402 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9404 case RENDERPATH_GL13:
9405 case RENDERPATH_GL11:
9406 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9408 // apply a color tint to the whole view
9409 R_ResetViewRendering2D();
9410 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9411 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9412 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9413 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9414 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9420 matrix4x4_t r_waterscrollmatrix;
9422 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9424 if (r_refdef.fog_density)
9426 r_refdef.fogcolor[0] = r_refdef.fog_red;
9427 r_refdef.fogcolor[1] = r_refdef.fog_green;
9428 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9430 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9431 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9432 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9433 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9437 VectorCopy(r_refdef.fogcolor, fogvec);
9438 // color.rgb *= ContrastBoost * SceneBrightness;
9439 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9440 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9441 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9442 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9447 void R_UpdateVariables(void)
9451 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9453 r_refdef.farclip = r_farclip_base.value;
9454 if (r_refdef.scene.worldmodel)
9455 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9456 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9458 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9459 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9460 r_refdef.polygonfactor = 0;
9461 r_refdef.polygonoffset = 0;
9462 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9463 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9465 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9466 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9467 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
9468 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9469 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9470 if (FAKELIGHT_ENABLED)
9472 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
9474 if (r_showsurfaces.integer)
9476 r_refdef.scene.rtworld = false;
9477 r_refdef.scene.rtworldshadows = false;
9478 r_refdef.scene.rtdlight = false;
9479 r_refdef.scene.rtdlightshadows = false;
9480 r_refdef.lightmapintensity = 0;
9483 if (gamemode == GAME_NEHAHRA)
9485 if (gl_fogenable.integer)
9487 r_refdef.oldgl_fogenable = true;
9488 r_refdef.fog_density = gl_fogdensity.value;
9489 r_refdef.fog_red = gl_fogred.value;
9490 r_refdef.fog_green = gl_foggreen.value;
9491 r_refdef.fog_blue = gl_fogblue.value;
9492 r_refdef.fog_alpha = 1;
9493 r_refdef.fog_start = 0;
9494 r_refdef.fog_end = gl_skyclip.value;
9495 r_refdef.fog_height = 1<<30;
9496 r_refdef.fog_fadedepth = 128;
9498 else if (r_refdef.oldgl_fogenable)
9500 r_refdef.oldgl_fogenable = false;
9501 r_refdef.fog_density = 0;
9502 r_refdef.fog_red = 0;
9503 r_refdef.fog_green = 0;
9504 r_refdef.fog_blue = 0;
9505 r_refdef.fog_alpha = 0;
9506 r_refdef.fog_start = 0;
9507 r_refdef.fog_end = 0;
9508 r_refdef.fog_height = 1<<30;
9509 r_refdef.fog_fadedepth = 128;
9513 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9514 r_refdef.fog_start = max(0, r_refdef.fog_start);
9515 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9517 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9519 if (r_refdef.fog_density && r_drawfog.integer)
9521 r_refdef.fogenabled = true;
9522 // this is the point where the fog reaches 0.9986 alpha, which we
9523 // consider a good enough cutoff point for the texture
9524 // (0.9986 * 256 == 255.6)
9525 if (r_fog_exp2.integer)
9526 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9528 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9529 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9530 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9531 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9532 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9533 R_BuildFogHeightTexture();
9534 // fog color was already set
9535 // update the fog texture
9536 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)
9537 R_BuildFogTexture();
9538 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9539 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9542 r_refdef.fogenabled = false;
9544 switch(vid.renderpath)
9546 case RENDERPATH_GL20:
9547 case RENDERPATH_CGGL:
9548 case RENDERPATH_D3D9:
9549 case RENDERPATH_D3D10:
9550 case RENDERPATH_D3D11:
9551 if(v_glslgamma.integer && !vid_gammatables_trivial)
9553 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9555 // build GLSL gamma texture
9556 #define RAMPWIDTH 256
9557 unsigned short ramp[RAMPWIDTH * 3];
9558 unsigned char rampbgr[RAMPWIDTH][4];
9561 r_texture_gammaramps_serial = vid_gammatables_serial;
9563 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9564 for(i = 0; i < RAMPWIDTH; ++i)
9566 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9567 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9568 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9571 if (r_texture_gammaramps)
9573 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9577 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9583 // remove GLSL gamma texture
9586 case RENDERPATH_GL13:
9587 case RENDERPATH_GL11:
9592 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9593 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9599 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9600 if( scenetype != r_currentscenetype ) {
9601 // store the old scenetype
9602 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9603 r_currentscenetype = scenetype;
9604 // move in the new scene
9605 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9614 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9616 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9617 if( scenetype == r_currentscenetype ) {
9618 return &r_refdef.scene;
9620 return &r_scenes_store[ scenetype ];
9629 void R_RenderView(void)
9631 if (r_timereport_active)
9632 R_TimeReport("start");
9633 r_textureframe++; // used only by R_GetCurrentTexture
9634 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9636 if(R_CompileShader_CheckStaticParms())
9639 if (!r_drawentities.integer)
9640 r_refdef.scene.numentities = 0;
9642 R_AnimCache_ClearCache();
9643 R_FrameData_NewFrame();
9645 if (r_refdef.view.isoverlay)
9647 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9648 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9649 R_TimeReport("depthclear");
9651 r_refdef.view.showdebug = false;
9653 r_waterstate.enabled = false;
9654 r_waterstate.numwaterplanes = 0;
9662 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9663 return; //Host_Error ("R_RenderView: NULL worldmodel");
9665 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9667 R_RenderView_UpdateViewVectors();
9669 R_Shadow_UpdateWorldLightSelection();
9671 R_Bloom_StartFrame();
9672 R_Water_StartFrame();
9675 if (r_timereport_active)
9676 R_TimeReport("viewsetup");
9678 R_ResetViewRendering3D();
9680 if (r_refdef.view.clear || r_refdef.fogenabled)
9682 R_ClearScreen(r_refdef.fogenabled);
9683 if (r_timereport_active)
9684 R_TimeReport("viewclear");
9686 r_refdef.view.clear = true;
9688 // this produces a bloom texture to be used in R_BlendView() later
9689 if (r_hdr.integer && r_bloomstate.bloomwidth)
9691 R_HDR_RenderBloomTexture();
9692 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9693 r_textureframe++; // used only by R_GetCurrentTexture
9696 r_refdef.view.showdebug = true;
9699 if (r_timereport_active)
9700 R_TimeReport("visibility");
9702 r_waterstate.numwaterplanes = 0;
9703 if (r_waterstate.enabled)
9704 R_RenderWaterPlanes();
9707 r_waterstate.numwaterplanes = 0;
9710 if (r_timereport_active)
9711 R_TimeReport("blendview");
9713 GL_Scissor(0, 0, vid.width, vid.height);
9714 GL_ScissorTest(false);
9719 void R_RenderWaterPlanes(void)
9721 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9723 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9724 if (r_timereport_active)
9725 R_TimeReport("waterworld");
9728 // don't let sound skip if going slow
9729 if (r_refdef.scene.extraupdate)
9732 R_DrawModelsAddWaterPlanes();
9733 if (r_timereport_active)
9734 R_TimeReport("watermodels");
9736 if (r_waterstate.numwaterplanes)
9738 R_Water_ProcessPlanes();
9739 if (r_timereport_active)
9740 R_TimeReport("waterscenes");
9744 extern void R_DrawLightningBeams (void);
9745 extern void VM_CL_AddPolygonsToMeshQueue (void);
9746 extern void R_DrawPortals (void);
9747 extern cvar_t cl_locs_show;
9748 static void R_DrawLocs(void);
9749 static void R_DrawEntityBBoxes(void);
9750 static void R_DrawModelDecals(void);
9751 extern void R_DrawModelShadows(void);
9752 extern void R_DrawModelShadowMaps(void);
9753 extern cvar_t cl_decals_newsystem;
9754 extern qboolean r_shadow_usingdeferredprepass;
9755 void R_RenderScene(void)
9757 qboolean shadowmapping = false;
9759 if (r_timereport_active)
9760 R_TimeReport("beginscene");
9762 r_refdef.stats.renders++;
9766 // don't let sound skip if going slow
9767 if (r_refdef.scene.extraupdate)
9770 R_MeshQueue_BeginScene();
9774 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);
9776 if (r_timereport_active)
9777 R_TimeReport("skystartframe");
9779 if (cl.csqc_vidvars.drawworld)
9781 // don't let sound skip if going slow
9782 if (r_refdef.scene.extraupdate)
9785 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9787 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9788 if (r_timereport_active)
9789 R_TimeReport("worldsky");
9792 if (R_DrawBrushModelsSky() && r_timereport_active)
9793 R_TimeReport("bmodelsky");
9795 if (skyrendermasked && skyrenderlater)
9797 // we have to force off the water clipping plane while rendering sky
9801 if (r_timereport_active)
9802 R_TimeReport("sky");
9806 R_AnimCache_CacheVisibleEntities();
9807 if (r_timereport_active)
9808 R_TimeReport("animation");
9810 R_Shadow_PrepareLights();
9811 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9812 R_Shadow_PrepareModelShadows();
9813 if (r_timereport_active)
9814 R_TimeReport("preparelights");
9816 if (R_Shadow_ShadowMappingEnabled())
9817 shadowmapping = true;
9819 if (r_shadow_usingdeferredprepass)
9820 R_Shadow_DrawPrepass();
9822 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9824 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9825 if (r_timereport_active)
9826 R_TimeReport("worlddepth");
9828 if (r_depthfirst.integer >= 2)
9830 R_DrawModelsDepth();
9831 if (r_timereport_active)
9832 R_TimeReport("modeldepth");
9835 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9837 R_DrawModelShadowMaps();
9838 R_ResetViewRendering3D();
9839 // don't let sound skip if going slow
9840 if (r_refdef.scene.extraupdate)
9844 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9846 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9847 if (r_timereport_active)
9848 R_TimeReport("world");
9851 // don't let sound skip if going slow
9852 if (r_refdef.scene.extraupdate)
9856 if (r_timereport_active)
9857 R_TimeReport("models");
9859 // don't let sound skip if going slow
9860 if (r_refdef.scene.extraupdate)
9863 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9865 R_DrawModelShadows();
9866 R_ResetViewRendering3D();
9867 // don't let sound skip if going slow
9868 if (r_refdef.scene.extraupdate)
9872 if (!r_shadow_usingdeferredprepass)
9874 R_Shadow_DrawLights();
9875 if (r_timereport_active)
9876 R_TimeReport("rtlights");
9879 // don't let sound skip if going slow
9880 if (r_refdef.scene.extraupdate)
9883 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9885 R_DrawModelShadows();
9886 R_ResetViewRendering3D();
9887 // don't let sound skip if going slow
9888 if (r_refdef.scene.extraupdate)
9892 if (cl.csqc_vidvars.drawworld)
9894 if (cl_decals_newsystem.integer)
9896 R_DrawModelDecals();
9897 if (r_timereport_active)
9898 R_TimeReport("modeldecals");
9903 if (r_timereport_active)
9904 R_TimeReport("decals");
9908 if (r_timereport_active)
9909 R_TimeReport("particles");
9912 if (r_timereport_active)
9913 R_TimeReport("explosions");
9915 R_DrawLightningBeams();
9916 if (r_timereport_active)
9917 R_TimeReport("lightning");
9920 VM_CL_AddPolygonsToMeshQueue();
9922 if (r_refdef.view.showdebug)
9924 if (cl_locs_show.integer)
9927 if (r_timereport_active)
9928 R_TimeReport("showlocs");
9931 if (r_drawportals.integer)
9934 if (r_timereport_active)
9935 R_TimeReport("portals");
9938 if (r_showbboxes.value > 0)
9940 R_DrawEntityBBoxes();
9941 if (r_timereport_active)
9942 R_TimeReport("bboxes");
9946 R_MeshQueue_RenderTransparent();
9947 if (r_timereport_active)
9948 R_TimeReport("drawtrans");
9950 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))
9952 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9953 if (r_timereport_active)
9954 R_TimeReport("worlddebug");
9955 R_DrawModelsDebug();
9956 if (r_timereport_active)
9957 R_TimeReport("modeldebug");
9960 if (cl.csqc_vidvars.drawworld)
9962 R_Shadow_DrawCoronas();
9963 if (r_timereport_active)
9964 R_TimeReport("coronas");
9969 GL_DepthTest(false);
9970 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9971 GL_Color(1, 1, 1, 1);
9972 qglBegin(GL_POLYGON);
9973 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
9974 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
9975 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
9976 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
9978 qglBegin(GL_POLYGON);
9979 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]);
9980 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]);
9981 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]);
9982 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]);
9984 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9988 // don't let sound skip if going slow
9989 if (r_refdef.scene.extraupdate)
9992 R_ResetViewRendering2D();
9995 static const unsigned short bboxelements[36] =
10005 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
10008 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
10010 RSurf_ActiveWorldEntity();
10012 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10013 GL_DepthMask(false);
10014 GL_DepthRange(0, 1);
10015 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10016 // R_Mesh_ResetTextureState();
10018 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
10019 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
10020 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
10021 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
10022 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
10023 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
10024 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
10025 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
10026 R_FillColors(color4f, 8, cr, cg, cb, ca);
10027 if (r_refdef.fogenabled)
10029 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
10031 f1 = RSurf_FogVertex(v);
10033 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
10034 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
10035 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
10038 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
10039 R_Mesh_ResetTextureState();
10040 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10041 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
10044 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10048 prvm_edict_t *edict;
10049 prvm_prog_t *prog_save = prog;
10051 // this function draws bounding boxes of server entities
10055 GL_CullFace(GL_NONE);
10056 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10060 for (i = 0;i < numsurfaces;i++)
10062 edict = PRVM_EDICT_NUM(surfacelist[i]);
10063 switch ((int)edict->fields.server->solid)
10065 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
10066 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
10067 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
10068 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
10069 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
10070 default: Vector4Set(color, 0, 0, 0, 0.50);break;
10072 color[3] *= r_showbboxes.value;
10073 color[3] = bound(0, color[3], 1);
10074 GL_DepthTest(!r_showdisabledepthtest.integer);
10075 GL_CullFace(r_refdef.view.cullface_front);
10076 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
10082 static void R_DrawEntityBBoxes(void)
10085 prvm_edict_t *edict;
10087 prvm_prog_t *prog_save = prog;
10089 // this function draws bounding boxes of server entities
10095 for (i = 0;i < prog->num_edicts;i++)
10097 edict = PRVM_EDICT_NUM(i);
10098 if (edict->priv.server->free)
10100 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
10101 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
10103 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
10105 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
10106 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
10112 static const int nomodelelement3i[24] =
10124 static const unsigned short nomodelelement3s[24] =
10136 static const float nomodelvertex3f[6*3] =
10146 static const float nomodelcolor4f[6*4] =
10148 0.0f, 0.0f, 0.5f, 1.0f,
10149 0.0f, 0.0f, 0.5f, 1.0f,
10150 0.0f, 0.5f, 0.0f, 1.0f,
10151 0.0f, 0.5f, 0.0f, 1.0f,
10152 0.5f, 0.0f, 0.0f, 1.0f,
10153 0.5f, 0.0f, 0.0f, 1.0f
10156 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10160 float color4f[6*4];
10162 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);
10164 // this is only called once per entity so numsurfaces is always 1, and
10165 // surfacelist is always {0}, so this code does not handle batches
10167 if (rsurface.ent_flags & RENDER_ADDITIVE)
10169 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
10170 GL_DepthMask(false);
10172 else if (rsurface.colormod[3] < 1)
10174 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10175 GL_DepthMask(false);
10179 GL_BlendFunc(GL_ONE, GL_ZERO);
10180 GL_DepthMask(true);
10182 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
10183 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
10184 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
10185 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
10186 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
10187 for (i = 0, c = color4f;i < 6;i++, c += 4)
10189 c[0] *= rsurface.colormod[0];
10190 c[1] *= rsurface.colormod[1];
10191 c[2] *= rsurface.colormod[2];
10192 c[3] *= rsurface.colormod[3];
10194 if (r_refdef.fogenabled)
10196 for (i = 0, c = color4f;i < 6;i++, c += 4)
10198 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
10200 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
10201 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
10202 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
10205 // R_Mesh_ResetTextureState();
10206 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10207 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
10208 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
10211 void R_DrawNoModel(entity_render_t *ent)
10214 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
10215 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
10216 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
10218 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
10221 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
10223 vec3_t right1, right2, diff, normal;
10225 VectorSubtract (org2, org1, normal);
10227 // calculate 'right' vector for start
10228 VectorSubtract (r_refdef.view.origin, org1, diff);
10229 CrossProduct (normal, diff, right1);
10230 VectorNormalize (right1);
10232 // calculate 'right' vector for end
10233 VectorSubtract (r_refdef.view.origin, org2, diff);
10234 CrossProduct (normal, diff, right2);
10235 VectorNormalize (right2);
10237 vert[ 0] = org1[0] + width * right1[0];
10238 vert[ 1] = org1[1] + width * right1[1];
10239 vert[ 2] = org1[2] + width * right1[2];
10240 vert[ 3] = org1[0] - width * right1[0];
10241 vert[ 4] = org1[1] - width * right1[1];
10242 vert[ 5] = org1[2] - width * right1[2];
10243 vert[ 6] = org2[0] - width * right2[0];
10244 vert[ 7] = org2[1] - width * right2[1];
10245 vert[ 8] = org2[2] - width * right2[2];
10246 vert[ 9] = org2[0] + width * right2[0];
10247 vert[10] = org2[1] + width * right2[1];
10248 vert[11] = org2[2] + width * right2[2];
10251 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)
10253 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
10254 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
10255 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
10256 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
10257 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
10258 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
10259 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
10260 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
10261 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
10262 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
10263 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
10264 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
10267 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
10272 VectorSet(v, x, y, z);
10273 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
10274 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
10276 if (i == mesh->numvertices)
10278 if (mesh->numvertices < mesh->maxvertices)
10280 VectorCopy(v, vertex3f);
10281 mesh->numvertices++;
10283 return mesh->numvertices;
10289 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
10292 int *e, element[3];
10293 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10294 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10295 e = mesh->element3i + mesh->numtriangles * 3;
10296 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
10298 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
10299 if (mesh->numtriangles < mesh->maxtriangles)
10304 mesh->numtriangles++;
10306 element[1] = element[2];
10310 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
10313 int *e, element[3];
10314 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10315 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10316 e = mesh->element3i + mesh->numtriangles * 3;
10317 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10319 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10320 if (mesh->numtriangles < mesh->maxtriangles)
10325 mesh->numtriangles++;
10327 element[1] = element[2];
10331 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10332 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10334 int planenum, planenum2;
10337 mplane_t *plane, *plane2;
10339 double temppoints[2][256*3];
10340 // figure out how large a bounding box we need to properly compute this brush
10342 for (w = 0;w < numplanes;w++)
10343 maxdist = max(maxdist, fabs(planes[w].dist));
10344 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10345 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10346 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10350 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10351 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10353 if (planenum2 == planenum)
10355 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);
10358 if (tempnumpoints < 3)
10360 // generate elements forming a triangle fan for this polygon
10361 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10365 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)
10367 texturelayer_t *layer;
10368 layer = t->currentlayers + t->currentnumlayers++;
10369 layer->type = type;
10370 layer->depthmask = depthmask;
10371 layer->blendfunc1 = blendfunc1;
10372 layer->blendfunc2 = blendfunc2;
10373 layer->texture = texture;
10374 layer->texmatrix = *matrix;
10375 layer->color[0] = r;
10376 layer->color[1] = g;
10377 layer->color[2] = b;
10378 layer->color[3] = a;
10381 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10383 if(parms[0] == 0 && parms[1] == 0)
10385 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10386 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10391 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10394 index = parms[2] + r_refdef.scene.time * parms[3];
10395 index -= floor(index);
10396 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10399 case Q3WAVEFUNC_NONE:
10400 case Q3WAVEFUNC_NOISE:
10401 case Q3WAVEFUNC_COUNT:
10404 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10405 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10406 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10407 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10408 case Q3WAVEFUNC_TRIANGLE:
10410 f = index - floor(index);
10413 else if (index < 2)
10415 else if (index < 3)
10421 f = parms[0] + parms[1] * f;
10422 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10423 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10427 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10432 matrix4x4_t matrix, temp;
10433 switch(tcmod->tcmod)
10435 case Q3TCMOD_COUNT:
10437 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10438 matrix = r_waterscrollmatrix;
10440 matrix = identitymatrix;
10442 case Q3TCMOD_ENTITYTRANSLATE:
10443 // this is used in Q3 to allow the gamecode to control texcoord
10444 // scrolling on the entity, which is not supported in darkplaces yet.
10445 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10447 case Q3TCMOD_ROTATE:
10448 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10449 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10450 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10452 case Q3TCMOD_SCALE:
10453 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10455 case Q3TCMOD_SCROLL:
10456 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10458 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10459 w = (int) tcmod->parms[0];
10460 h = (int) tcmod->parms[1];
10461 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10463 idx = (int) floor(f * w * h);
10464 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10466 case Q3TCMOD_STRETCH:
10467 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10468 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10470 case Q3TCMOD_TRANSFORM:
10471 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
10472 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
10473 VectorSet(tcmat + 6, 0 , 0 , 1);
10474 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
10475 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10477 case Q3TCMOD_TURBULENT:
10478 // this is handled in the RSurf_PrepareVertices function
10479 matrix = identitymatrix;
10483 Matrix4x4_Concat(texmatrix, &matrix, &temp);
10486 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10488 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10489 char name[MAX_QPATH];
10490 skinframe_t *skinframe;
10491 unsigned char pixels[296*194];
10492 strlcpy(cache->name, skinname, sizeof(cache->name));
10493 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10494 if (developer_loading.integer)
10495 Con_Printf("loading %s\n", name);
10496 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10497 if (!skinframe || !skinframe->base)
10500 fs_offset_t filesize;
10502 f = FS_LoadFile(name, tempmempool, true, &filesize);
10505 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10506 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10510 cache->skinframe = skinframe;
10513 texture_t *R_GetCurrentTexture(texture_t *t)
10516 const entity_render_t *ent = rsurface.entity;
10517 dp_model_t *model = ent->model;
10518 q3shaderinfo_layer_tcmod_t *tcmod;
10520 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10521 return t->currentframe;
10522 t->update_lastrenderframe = r_textureframe;
10523 t->update_lastrenderentity = (void *)ent;
10525 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10526 t->camera_entity = ent->entitynumber;
10528 t->camera_entity = 0;
10530 // switch to an alternate material if this is a q1bsp animated material
10532 texture_t *texture = t;
10533 int s = rsurface.ent_skinnum;
10534 if ((unsigned int)s >= (unsigned int)model->numskins)
10536 if (model->skinscenes)
10538 if (model->skinscenes[s].framecount > 1)
10539 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10541 s = model->skinscenes[s].firstframe;
10544 t = t + s * model->num_surfaces;
10547 // use an alternate animation if the entity's frame is not 0,
10548 // and only if the texture has an alternate animation
10549 if (rsurface.ent_alttextures && t->anim_total[1])
10550 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10552 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10554 texture->currentframe = t;
10557 // update currentskinframe to be a qw skin or animation frame
10558 if (rsurface.ent_qwskin >= 0)
10560 i = rsurface.ent_qwskin;
10561 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10563 r_qwskincache_size = cl.maxclients;
10565 Mem_Free(r_qwskincache);
10566 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10568 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10569 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10570 t->currentskinframe = r_qwskincache[i].skinframe;
10571 if (t->currentskinframe == NULL)
10572 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10574 else if (t->numskinframes >= 2)
10575 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10576 if (t->backgroundnumskinframes >= 2)
10577 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10579 t->currentmaterialflags = t->basematerialflags;
10580 t->currentalpha = rsurface.colormod[3];
10581 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10582 t->currentalpha *= r_wateralpha.value;
10583 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10584 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10585 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10586 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10587 if (!(rsurface.ent_flags & RENDER_LIGHT))
10588 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10589 else if (FAKELIGHT_ENABLED)
10591 // no modellight if using fakelight for the map
10593 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10595 // pick a model lighting mode
10596 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10597 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10599 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10601 if (rsurface.ent_flags & RENDER_ADDITIVE)
10602 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10603 else if (t->currentalpha < 1)
10604 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10605 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10606 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10607 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10608 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10609 if (t->backgroundnumskinframes)
10610 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10611 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10613 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10614 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10617 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10618 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10619 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10621 // there is no tcmod
10622 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10624 t->currenttexmatrix = r_waterscrollmatrix;
10625 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10627 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10629 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10630 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10633 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10634 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10635 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10636 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10638 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10639 if (t->currentskinframe->qpixels)
10640 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10641 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10642 if (!t->basetexture)
10643 t->basetexture = r_texture_notexture;
10644 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10645 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10646 t->nmaptexture = t->currentskinframe->nmap;
10647 if (!t->nmaptexture)
10648 t->nmaptexture = r_texture_blanknormalmap;
10649 t->glosstexture = r_texture_black;
10650 t->glowtexture = t->currentskinframe->glow;
10651 t->fogtexture = t->currentskinframe->fog;
10652 t->reflectmasktexture = t->currentskinframe->reflect;
10653 if (t->backgroundnumskinframes)
10655 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10656 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10657 t->backgroundglosstexture = r_texture_black;
10658 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10659 if (!t->backgroundnmaptexture)
10660 t->backgroundnmaptexture = r_texture_blanknormalmap;
10664 t->backgroundbasetexture = r_texture_white;
10665 t->backgroundnmaptexture = r_texture_blanknormalmap;
10666 t->backgroundglosstexture = r_texture_black;
10667 t->backgroundglowtexture = NULL;
10669 t->specularpower = r_shadow_glossexponent.value;
10670 // TODO: store reference values for these in the texture?
10671 t->specularscale = 0;
10672 if (r_shadow_gloss.integer > 0)
10674 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10676 if (r_shadow_glossintensity.value > 0)
10678 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10679 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10680 t->specularscale = r_shadow_glossintensity.value;
10683 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10685 t->glosstexture = r_texture_white;
10686 t->backgroundglosstexture = r_texture_white;
10687 t->specularscale = r_shadow_gloss2intensity.value;
10688 t->specularpower = r_shadow_gloss2exponent.value;
10691 t->specularscale *= t->specularscalemod;
10692 t->specularpower *= t->specularpowermod;
10694 // lightmaps mode looks bad with dlights using actual texturing, so turn
10695 // off the colormap and glossmap, but leave the normalmap on as it still
10696 // accurately represents the shading involved
10697 if (gl_lightmaps.integer)
10699 t->basetexture = r_texture_grey128;
10700 t->pantstexture = r_texture_black;
10701 t->shirttexture = r_texture_black;
10702 t->nmaptexture = r_texture_blanknormalmap;
10703 t->glosstexture = r_texture_black;
10704 t->glowtexture = NULL;
10705 t->fogtexture = NULL;
10706 t->reflectmasktexture = NULL;
10707 t->backgroundbasetexture = NULL;
10708 t->backgroundnmaptexture = r_texture_blanknormalmap;
10709 t->backgroundglosstexture = r_texture_black;
10710 t->backgroundglowtexture = NULL;
10711 t->specularscale = 0;
10712 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10715 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10716 VectorClear(t->dlightcolor);
10717 t->currentnumlayers = 0;
10718 if (t->currentmaterialflags & MATERIALFLAG_WALL)
10720 int blendfunc1, blendfunc2;
10721 qboolean depthmask;
10722 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10724 blendfunc1 = GL_SRC_ALPHA;
10725 blendfunc2 = GL_ONE;
10727 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10729 blendfunc1 = GL_SRC_ALPHA;
10730 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10732 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10734 blendfunc1 = t->customblendfunc[0];
10735 blendfunc2 = t->customblendfunc[1];
10739 blendfunc1 = GL_ONE;
10740 blendfunc2 = GL_ZERO;
10742 // don't colormod evilblend textures
10743 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10744 VectorSet(t->lightmapcolor, 1, 1, 1);
10745 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10746 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10748 // fullbright is not affected by r_refdef.lightmapintensity
10749 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]);
10750 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10751 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]);
10752 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10753 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]);
10757 vec3_t ambientcolor;
10759 // set the color tint used for lights affecting this surface
10760 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10762 // q3bsp has no lightmap updates, so the lightstylevalue that
10763 // would normally be baked into the lightmap must be
10764 // applied to the color
10765 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10766 if (model->type == mod_brushq3)
10767 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10768 colorscale *= r_refdef.lightmapintensity;
10769 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10770 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10771 // basic lit geometry
10772 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]);
10773 // add pants/shirt if needed
10774 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10775 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]);
10776 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10777 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]);
10778 // now add ambient passes if needed
10779 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10781 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]);
10782 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10783 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]);
10784 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10785 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]);
10788 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10789 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]);
10790 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10792 // if this is opaque use alpha blend which will darken the earlier
10795 // if this is an alpha blended material, all the earlier passes
10796 // were darkened by fog already, so we only need to add the fog
10797 // color ontop through the fog mask texture
10799 // if this is an additive blended material, all the earlier passes
10800 // were darkened by fog already, and we should not add fog color
10801 // (because the background was not darkened, there is no fog color
10802 // that was lost behind it).
10803 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]);
10807 return t->currentframe;
10810 rsurfacestate_t rsurface;
10812 void R_Mesh_ResizeArrays(int newvertices)
10814 unsigned char *base;
10816 if (rsurface.array_size >= newvertices)
10818 if (rsurface.array_base)
10819 Mem_Free(rsurface.array_base);
10820 rsurface.array_size = (newvertices + 1023) & ~1023;
10822 size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10823 size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10824 size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10825 size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10826 size += rsurface.array_size * sizeof(float[3]);
10827 size += rsurface.array_size * sizeof(float[3]);
10828 size += rsurface.array_size * sizeof(float[3]);
10829 size += rsurface.array_size * sizeof(float[3]);
10830 size += rsurface.array_size * sizeof(float[3]);
10831 size += rsurface.array_size * sizeof(float[3]);
10832 size += rsurface.array_size * sizeof(float[3]);
10833 size += rsurface.array_size * sizeof(float[3]);
10834 size += rsurface.array_size * sizeof(float[4]);
10835 size += rsurface.array_size * sizeof(float[2]);
10836 size += rsurface.array_size * sizeof(float[2]);
10837 size += rsurface.array_size * sizeof(float[4]);
10838 size += rsurface.array_size * sizeof(int[3]);
10839 size += rsurface.array_size * sizeof(unsigned short[3]);
10840 rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
10841 rsurface.array_modelvertexmesh = (r_vertexmesh_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10842 rsurface.array_batchvertexmesh = (r_vertexmesh_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10843 rsurface.array_modelvertexposition = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10844 rsurface.array_batchvertexposition = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10845 rsurface.array_modelvertex3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10846 rsurface.array_modelsvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10847 rsurface.array_modeltvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10848 rsurface.array_modelnormal3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10849 rsurface.array_batchvertex3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10850 rsurface.array_batchsvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10851 rsurface.array_batchtvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10852 rsurface.array_batchnormal3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10853 rsurface.array_batchlightmapcolor4f = (float *)base;base += rsurface.array_size * sizeof(float[4]);
10854 rsurface.array_batchtexcoordtexture2f = (float *)base;base += rsurface.array_size * sizeof(float[2]);
10855 rsurface.array_batchtexcoordlightmap2f = (float *)base;base += rsurface.array_size * sizeof(float[2]);
10856 rsurface.array_passcolor4f = (float *)base;base += rsurface.array_size * sizeof(float[4]);
10857 rsurface.array_batchelement3i = (int *)base;base += rsurface.array_size * sizeof(int[3]);
10858 rsurface.array_batchelement3s = (unsigned short *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
10861 void RSurf_ActiveWorldEntity(void)
10863 dp_model_t *model = r_refdef.scene.worldmodel;
10864 //if (rsurface.entity == r_refdef.scene.worldentity)
10866 rsurface.entity = r_refdef.scene.worldentity;
10867 rsurface.skeleton = NULL;
10868 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10869 rsurface.ent_skinnum = 0;
10870 rsurface.ent_qwskin = -1;
10871 rsurface.ent_shadertime = 0;
10872 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10873 R_Mesh_ResizeArrays(max(model->surfmesh.num_vertices, model->surfmesh.num_triangles));
10874 rsurface.matrix = identitymatrix;
10875 rsurface.inversematrix = identitymatrix;
10876 rsurface.matrixscale = 1;
10877 rsurface.inversematrixscale = 1;
10878 R_EntityMatrix(&identitymatrix);
10879 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10880 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10881 rsurface.fograngerecip = r_refdef.fograngerecip;
10882 rsurface.fogheightfade = r_refdef.fogheightfade;
10883 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10884 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10885 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10886 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10887 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10888 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10889 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10890 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10891 rsurface.colormod[3] = 1;
10892 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);
10893 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10894 rsurface.frameblend[0].lerp = 1;
10895 rsurface.ent_alttextures = false;
10896 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10897 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10898 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
10899 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10900 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10901 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10902 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10903 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10904 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10905 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10906 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10907 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
10908 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10909 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10910 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
10911 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10912 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10913 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
10914 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10915 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10916 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
10917 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10918 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10919 rsurface.modelelement3i = model->surfmesh.data_element3i;
10920 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10921 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10922 rsurface.modelelement3s = model->surfmesh.data_element3s;
10923 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10924 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10925 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10926 rsurface.modelnumvertices = model->surfmesh.num_vertices;
10927 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10928 rsurface.modelsurfaces = model->data_surfaces;
10929 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10930 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10931 rsurface.modelvertexposition = model->surfmesh.vertexposition;
10932 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10933 rsurface.modelgeneratedvertex = false;
10934 rsurface.batchgeneratedvertex = false;
10935 rsurface.batchfirstvertex = 0;
10936 rsurface.batchnumvertices = 0;
10937 rsurface.batchfirsttriangle = 0;
10938 rsurface.batchnumtriangles = 0;
10939 rsurface.batchvertex3f = NULL;
10940 rsurface.batchvertex3f_vertexbuffer = NULL;
10941 rsurface.batchvertex3f_bufferoffset = 0;
10942 rsurface.batchsvector3f = NULL;
10943 rsurface.batchsvector3f_vertexbuffer = NULL;
10944 rsurface.batchsvector3f_bufferoffset = 0;
10945 rsurface.batchtvector3f = NULL;
10946 rsurface.batchtvector3f_vertexbuffer = NULL;
10947 rsurface.batchtvector3f_bufferoffset = 0;
10948 rsurface.batchnormal3f = NULL;
10949 rsurface.batchnormal3f_vertexbuffer = NULL;
10950 rsurface.batchnormal3f_bufferoffset = 0;
10951 rsurface.batchlightmapcolor4f = NULL;
10952 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10953 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10954 rsurface.batchtexcoordtexture2f = NULL;
10955 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10956 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10957 rsurface.batchtexcoordlightmap2f = NULL;
10958 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10959 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10960 rsurface.batchvertexmesh = NULL;
10961 rsurface.batchvertexmeshbuffer = NULL;
10962 rsurface.batchvertexposition = NULL;
10963 rsurface.batchvertexpositionbuffer = NULL;
10964 rsurface.batchelement3i = NULL;
10965 rsurface.batchelement3i_indexbuffer = NULL;
10966 rsurface.batchelement3i_bufferoffset = 0;
10967 rsurface.batchelement3s = NULL;
10968 rsurface.batchelement3s_indexbuffer = NULL;
10969 rsurface.batchelement3s_bufferoffset = 0;
10970 rsurface.passcolor4f = NULL;
10971 rsurface.passcolor4f_vertexbuffer = NULL;
10972 rsurface.passcolor4f_bufferoffset = 0;
10975 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10977 dp_model_t *model = ent->model;
10978 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10980 rsurface.entity = (entity_render_t *)ent;
10981 rsurface.skeleton = ent->skeleton;
10982 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10983 rsurface.ent_skinnum = ent->skinnum;
10984 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;
10985 rsurface.ent_shadertime = ent->shadertime;
10986 rsurface.ent_flags = ent->flags;
10987 R_Mesh_ResizeArrays(max(model->surfmesh.num_vertices, model->surfmesh.num_triangles));
10988 rsurface.matrix = ent->matrix;
10989 rsurface.inversematrix = ent->inversematrix;
10990 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10991 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10992 R_EntityMatrix(&rsurface.matrix);
10993 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10994 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10995 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10996 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10997 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10998 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10999 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
11000 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
11001 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
11002 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
11003 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
11004 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
11005 rsurface.colormod[3] = ent->alpha;
11006 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
11007 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
11008 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
11009 rsurface.basepolygonfactor = r_refdef.polygonfactor;
11010 rsurface.basepolygonoffset = r_refdef.polygonoffset;
11011 if (ent->model->brush.submodel && !prepass)
11013 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
11014 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
11016 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
11018 if (ent->animcache_vertex3f && !r_framedata_failed)
11020 rsurface.modelvertex3f = ent->animcache_vertex3f;
11021 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
11022 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
11023 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
11024 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
11025 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
11026 rsurface.modelvertexposition = ent->animcache_vertexposition;
11027 rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
11029 else if (wanttangents)
11031 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11032 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11033 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11034 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11035 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
11036 rsurface.modelvertexmesh = NULL;
11037 rsurface.modelvertexmeshbuffer = NULL;
11038 rsurface.modelvertexposition = NULL;
11039 rsurface.modelvertexpositionbuffer = NULL;
11041 else if (wantnormals)
11043 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11044 rsurface.modelsvector3f = NULL;
11045 rsurface.modeltvector3f = NULL;
11046 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11047 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
11048 rsurface.modelvertexmesh = NULL;
11049 rsurface.modelvertexmeshbuffer = NULL;
11050 rsurface.modelvertexposition = NULL;
11051 rsurface.modelvertexpositionbuffer = NULL;
11055 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11056 rsurface.modelsvector3f = NULL;
11057 rsurface.modeltvector3f = NULL;
11058 rsurface.modelnormal3f = NULL;
11059 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
11060 rsurface.modelvertexmesh = NULL;
11061 rsurface.modelvertexmeshbuffer = NULL;
11062 rsurface.modelvertexposition = NULL;
11063 rsurface.modelvertexpositionbuffer = NULL;
11065 rsurface.modelvertex3f_vertexbuffer = 0;
11066 rsurface.modelvertex3f_bufferoffset = 0;
11067 rsurface.modelsvector3f_vertexbuffer = 0;
11068 rsurface.modelsvector3f_bufferoffset = 0;
11069 rsurface.modeltvector3f_vertexbuffer = 0;
11070 rsurface.modeltvector3f_bufferoffset = 0;
11071 rsurface.modelnormal3f_vertexbuffer = 0;
11072 rsurface.modelnormal3f_bufferoffset = 0;
11073 rsurface.modelgeneratedvertex = true;
11077 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
11078 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11079 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
11080 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
11081 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11082 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
11083 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
11084 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11085 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
11086 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
11087 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11088 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
11089 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
11090 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
11091 rsurface.modelvertexposition = model->surfmesh.vertexposition;
11092 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
11093 rsurface.modelgeneratedvertex = false;
11095 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
11096 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11097 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11098 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
11099 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11100 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11101 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
11102 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11103 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11104 rsurface.modelelement3i = model->surfmesh.data_element3i;
11105 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11106 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11107 rsurface.modelelement3s = model->surfmesh.data_element3s;
11108 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11109 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11110 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11111 rsurface.modelnumvertices = model->surfmesh.num_vertices;
11112 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11113 rsurface.modelsurfaces = model->data_surfaces;
11114 rsurface.batchgeneratedvertex = false;
11115 rsurface.batchfirstvertex = 0;
11116 rsurface.batchnumvertices = 0;
11117 rsurface.batchfirsttriangle = 0;
11118 rsurface.batchnumtriangles = 0;
11119 rsurface.batchvertex3f = NULL;
11120 rsurface.batchvertex3f_vertexbuffer = NULL;
11121 rsurface.batchvertex3f_bufferoffset = 0;
11122 rsurface.batchsvector3f = NULL;
11123 rsurface.batchsvector3f_vertexbuffer = NULL;
11124 rsurface.batchsvector3f_bufferoffset = 0;
11125 rsurface.batchtvector3f = NULL;
11126 rsurface.batchtvector3f_vertexbuffer = NULL;
11127 rsurface.batchtvector3f_bufferoffset = 0;
11128 rsurface.batchnormal3f = NULL;
11129 rsurface.batchnormal3f_vertexbuffer = NULL;
11130 rsurface.batchnormal3f_bufferoffset = 0;
11131 rsurface.batchlightmapcolor4f = NULL;
11132 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11133 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11134 rsurface.batchtexcoordtexture2f = NULL;
11135 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11136 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11137 rsurface.batchtexcoordlightmap2f = NULL;
11138 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11139 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11140 rsurface.batchvertexmesh = NULL;
11141 rsurface.batchvertexmeshbuffer = NULL;
11142 rsurface.batchvertexposition = NULL;
11143 rsurface.batchvertexpositionbuffer = NULL;
11144 rsurface.batchelement3i = NULL;
11145 rsurface.batchelement3i_indexbuffer = NULL;
11146 rsurface.batchelement3i_bufferoffset = 0;
11147 rsurface.batchelement3s = NULL;
11148 rsurface.batchelement3s_indexbuffer = NULL;
11149 rsurface.batchelement3s_bufferoffset = 0;
11150 rsurface.passcolor4f = NULL;
11151 rsurface.passcolor4f_vertexbuffer = NULL;
11152 rsurface.passcolor4f_bufferoffset = 0;
11155 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)
11159 rsurface.entity = r_refdef.scene.worldentity;
11160 rsurface.skeleton = NULL;
11161 rsurface.ent_skinnum = 0;
11162 rsurface.ent_qwskin = -1;
11163 rsurface.ent_shadertime = shadertime;
11164 rsurface.ent_flags = entflags;
11165 rsurface.modelnumvertices = numvertices;
11166 rsurface.modelnumtriangles = numtriangles;
11167 R_Mesh_ResizeArrays(max(rsurface.modelnumvertices, rsurface.modelnumtriangles));
11168 rsurface.matrix = *matrix;
11169 rsurface.inversematrix = *inversematrix;
11170 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11171 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11172 R_EntityMatrix(&rsurface.matrix);
11173 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11174 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11175 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11176 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11177 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11178 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11179 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11180 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11181 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11182 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11183 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11184 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
11185 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);
11186 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11187 rsurface.frameblend[0].lerp = 1;
11188 rsurface.ent_alttextures = false;
11189 rsurface.basepolygonfactor = r_refdef.polygonfactor;
11190 rsurface.basepolygonoffset = r_refdef.polygonoffset;
11193 rsurface.modelvertex3f = vertex3f;
11194 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
11195 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
11196 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11198 else if (wantnormals)
11200 rsurface.modelvertex3f = vertex3f;
11201 rsurface.modelsvector3f = NULL;
11202 rsurface.modeltvector3f = NULL;
11203 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11207 rsurface.modelvertex3f = vertex3f;
11208 rsurface.modelsvector3f = NULL;
11209 rsurface.modeltvector3f = NULL;
11210 rsurface.modelnormal3f = NULL;
11212 rsurface.modelvertexmesh = NULL;
11213 rsurface.modelvertexmeshbuffer = NULL;
11214 rsurface.modelvertexposition = NULL;
11215 rsurface.modelvertexpositionbuffer = NULL;
11216 rsurface.modelvertex3f_vertexbuffer = 0;
11217 rsurface.modelvertex3f_bufferoffset = 0;
11218 rsurface.modelsvector3f_vertexbuffer = 0;
11219 rsurface.modelsvector3f_bufferoffset = 0;
11220 rsurface.modeltvector3f_vertexbuffer = 0;
11221 rsurface.modeltvector3f_bufferoffset = 0;
11222 rsurface.modelnormal3f_vertexbuffer = 0;
11223 rsurface.modelnormal3f_bufferoffset = 0;
11224 rsurface.modelgeneratedvertex = true;
11225 rsurface.modellightmapcolor4f = color4f;
11226 rsurface.modellightmapcolor4f_vertexbuffer = 0;
11227 rsurface.modellightmapcolor4f_bufferoffset = 0;
11228 rsurface.modeltexcoordtexture2f = texcoord2f;
11229 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
11230 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
11231 rsurface.modeltexcoordlightmap2f = NULL;
11232 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
11233 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
11234 rsurface.modelelement3i = element3i;
11235 rsurface.modelelement3i_indexbuffer = NULL;
11236 rsurface.modelelement3i_bufferoffset = 0;
11237 rsurface.modelelement3s = element3s;
11238 rsurface.modelelement3s_indexbuffer = NULL;
11239 rsurface.modelelement3s_bufferoffset = 0;
11240 rsurface.modellightmapoffsets = NULL;
11241 rsurface.modelsurfaces = NULL;
11242 rsurface.batchgeneratedvertex = false;
11243 rsurface.batchfirstvertex = 0;
11244 rsurface.batchnumvertices = 0;
11245 rsurface.batchfirsttriangle = 0;
11246 rsurface.batchnumtriangles = 0;
11247 rsurface.batchvertex3f = NULL;
11248 rsurface.batchvertex3f_vertexbuffer = NULL;
11249 rsurface.batchvertex3f_bufferoffset = 0;
11250 rsurface.batchsvector3f = NULL;
11251 rsurface.batchsvector3f_vertexbuffer = NULL;
11252 rsurface.batchsvector3f_bufferoffset = 0;
11253 rsurface.batchtvector3f = NULL;
11254 rsurface.batchtvector3f_vertexbuffer = NULL;
11255 rsurface.batchtvector3f_bufferoffset = 0;
11256 rsurface.batchnormal3f = NULL;
11257 rsurface.batchnormal3f_vertexbuffer = NULL;
11258 rsurface.batchnormal3f_bufferoffset = 0;
11259 rsurface.batchlightmapcolor4f = NULL;
11260 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11261 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11262 rsurface.batchtexcoordtexture2f = NULL;
11263 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11264 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11265 rsurface.batchtexcoordlightmap2f = NULL;
11266 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11267 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11268 rsurface.batchvertexmesh = NULL;
11269 rsurface.batchvertexmeshbuffer = NULL;
11270 rsurface.batchvertexposition = NULL;
11271 rsurface.batchvertexpositionbuffer = NULL;
11272 rsurface.batchelement3i = NULL;
11273 rsurface.batchelement3i_indexbuffer = NULL;
11274 rsurface.batchelement3i_bufferoffset = 0;
11275 rsurface.batchelement3s = NULL;
11276 rsurface.batchelement3s_indexbuffer = NULL;
11277 rsurface.batchelement3s_bufferoffset = 0;
11278 rsurface.passcolor4f = NULL;
11279 rsurface.passcolor4f_vertexbuffer = NULL;
11280 rsurface.passcolor4f_bufferoffset = 0;
11282 if (rsurface.modelnumvertices && rsurface.modelelement3i)
11284 if ((wantnormals || wanttangents) && !normal3f)
11286 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
11287 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11289 if (wanttangents && !svector3f)
11291 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
11292 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11293 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11297 // now convert arrays into vertexmesh structs
11298 for (i = 0;i < numvertices;i++)
11300 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexposition[i].vertex3f);
11301 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexmesh[i].vertex3f);
11302 if (rsurface.modelsvector3f)
11303 VectorCopy(rsurface.modelsvector3f + 3*i, rsurface.array_modelvertexmesh[i].svector3f);
11304 if (rsurface.modeltvector3f)
11305 VectorCopy(rsurface.modeltvector3f + 3*i, rsurface.array_modelvertexmesh[i].tvector3f);
11306 if (rsurface.modelnormal3f)
11307 VectorCopy(rsurface.modelnormal3f + 3*i, rsurface.array_modelvertexmesh[i].normal3f);
11308 if (rsurface.modellightmapcolor4f)
11309 Vector4Scale(rsurface.modellightmapcolor4f + 4*i, 255.0f, rsurface.array_modelvertexmesh[i].color4ub);
11310 if (rsurface.modeltexcoordtexture2f)
11311 Vector2Copy(rsurface.modeltexcoordtexture2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordtexture2f);
11312 if (rsurface.modeltexcoordlightmap2f)
11313 Vector2Copy(rsurface.modeltexcoordlightmap2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordlightmap2f);
11317 float RSurf_FogPoint(const float *v)
11319 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11320 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11321 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11322 float FogHeightFade = r_refdef.fogheightfade;
11324 unsigned int fogmasktableindex;
11325 if (r_refdef.fogplaneviewabove)
11326 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11328 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11329 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11330 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11333 float RSurf_FogVertex(const float *v)
11335 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11336 float FogPlaneViewDist = rsurface.fogplaneviewdist;
11337 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11338 float FogHeightFade = rsurface.fogheightfade;
11340 unsigned int fogmasktableindex;
11341 if (r_refdef.fogplaneviewabove)
11342 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11344 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11345 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11346 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11349 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11352 for (i = 0;i < numelements;i++)
11353 outelement3i[i] = inelement3i[i] + adjust;
11356 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11357 extern cvar_t gl_vbo;
11358 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11366 int surfacefirsttriangle;
11367 int surfacenumtriangles;
11368 int surfacefirstvertex;
11369 int surfaceendvertex;
11370 int surfacenumvertices;
11374 qboolean dynamicvertex;
11378 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11379 float waveparms[4];
11380 q3shaderinfo_deform_t *deform;
11381 const msurface_t *surface, *firstsurface;
11382 r_vertexposition_t *vertexposition;
11383 r_vertexmesh_t *vertexmesh;
11384 if (!texturenumsurfaces)
11386 // find vertex range of this surface batch
11388 firstsurface = texturesurfacelist[0];
11389 firsttriangle = firstsurface->num_firsttriangle;
11391 firstvertex = endvertex = firstsurface->num_firstvertex;
11392 for (i = 0;i < texturenumsurfaces;i++)
11394 surface = texturesurfacelist[i];
11395 if (surface != firstsurface + i)
11397 surfacefirstvertex = surface->num_firstvertex;
11398 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11399 surfacenumtriangles = surface->num_triangles;
11400 if (firstvertex > surfacefirstvertex)
11401 firstvertex = surfacefirstvertex;
11402 if (endvertex < surfaceendvertex)
11403 endvertex = surfaceendvertex;
11404 numtriangles += surfacenumtriangles;
11407 // we now know the vertex range used, and if there are any gaps in it
11408 rsurface.batchfirstvertex = firstvertex;
11409 rsurface.batchnumvertices = endvertex - firstvertex;
11410 rsurface.batchfirsttriangle = firsttriangle;
11411 rsurface.batchnumtriangles = numtriangles;
11413 // this variable holds flags for which properties have been updated that
11414 // may require regenerating vertexmesh or vertexposition arrays...
11417 // check if any dynamic vertex processing must occur
11418 dynamicvertex = false;
11420 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11421 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
11422 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11424 switch (deform->deform)
11427 case Q3DEFORM_PROJECTIONSHADOW:
11428 case Q3DEFORM_TEXT0:
11429 case Q3DEFORM_TEXT1:
11430 case Q3DEFORM_TEXT2:
11431 case Q3DEFORM_TEXT3:
11432 case Q3DEFORM_TEXT4:
11433 case Q3DEFORM_TEXT5:
11434 case Q3DEFORM_TEXT6:
11435 case Q3DEFORM_TEXT7:
11436 case Q3DEFORM_NONE:
11438 case Q3DEFORM_AUTOSPRITE:
11439 dynamicvertex = true;
11440 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11441 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11443 case Q3DEFORM_AUTOSPRITE2:
11444 dynamicvertex = true;
11445 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11446 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11448 case Q3DEFORM_NORMAL:
11449 dynamicvertex = true;
11450 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11451 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11453 case Q3DEFORM_WAVE:
11454 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11455 break; // if wavefunc is a nop, ignore this transform
11456 dynamicvertex = true;
11457 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11458 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11460 case Q3DEFORM_BULGE:
11461 dynamicvertex = true;
11462 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11463 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11465 case Q3DEFORM_MOVE:
11466 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11467 break; // if wavefunc is a nop, ignore this transform
11468 dynamicvertex = true;
11469 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11470 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
11474 switch(rsurface.texture->tcgen.tcgen)
11477 case Q3TCGEN_TEXTURE:
11479 case Q3TCGEN_LIGHTMAP:
11480 dynamicvertex = true;
11481 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11482 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11484 case Q3TCGEN_VECTOR:
11485 dynamicvertex = true;
11486 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11487 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11489 case Q3TCGEN_ENVIRONMENT:
11490 dynamicvertex = true;
11491 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11492 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11495 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11497 dynamicvertex = true;
11498 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11499 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11502 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11504 dynamicvertex = true;
11505 batchneed |= BATCHNEED_NOGAPS;
11506 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11509 if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11511 dynamicvertex = true;
11512 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11513 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
11516 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11518 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11519 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
11520 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
11521 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
11522 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11523 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11524 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11527 // when the model data has no vertex buffer (dynamic mesh), we need to
11529 if (!rsurface.modelvertexmeshbuffer)
11530 batchneed |= BATCHNEED_NOGAPS;
11532 // if needsupdate, we have to do a dynamic vertex batch for sure
11533 if (needsupdate & batchneed)
11534 dynamicvertex = true;
11536 // see if we need to build vertexmesh from arrays
11537 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11538 dynamicvertex = true;
11540 // see if we need to build vertexposition from arrays
11541 if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
11542 dynamicvertex = true;
11544 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11545 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11546 dynamicvertex = true;
11548 // if there is a chance of animated vertex colors, it's a dynamic batch
11549 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11550 dynamicvertex = true;
11552 rsurface.batchvertex3f = rsurface.modelvertex3f;
11553 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11554 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11555 rsurface.batchsvector3f = rsurface.modelsvector3f;
11556 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11557 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11558 rsurface.batchtvector3f = rsurface.modeltvector3f;
11559 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11560 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11561 rsurface.batchnormal3f = rsurface.modelnormal3f;
11562 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11563 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11564 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11565 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
11566 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11567 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11568 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
11569 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
11570 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11571 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11572 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11573 rsurface.batchvertexposition = rsurface.modelvertexposition;
11574 rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
11575 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11576 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11577 rsurface.batchelement3i = rsurface.modelelement3i;
11578 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11579 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11580 rsurface.batchelement3s = rsurface.modelelement3s;
11581 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11582 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11584 // if any dynamic vertex processing has to occur in software, we copy the
11585 // entire surface list together before processing to rebase the vertices
11586 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11588 // if any gaps exist and we do not have a static vertex buffer, we have to
11589 // copy the surface list together to avoid wasting upload bandwidth on the
11590 // vertices in the gaps.
11592 // if gaps exist and we have a static vertex buffer, we still have to
11593 // combine the index buffer ranges into one dynamic index buffer.
11595 // in all cases we end up with data that can be drawn in one call.
11597 if (!dynamicvertex)
11599 // static vertex data, just set pointers...
11600 rsurface.batchgeneratedvertex = false;
11601 // if there are gaps, we want to build a combined index buffer,
11602 // otherwise use the original static buffer with an appropriate offset
11607 for (i = 0;i < texturenumsurfaces;i++)
11609 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11610 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11611 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11612 numtriangles += surfacenumtriangles;
11614 rsurface.batchelement3i = rsurface.array_batchelement3i;
11615 rsurface.batchelement3i_indexbuffer = NULL;
11616 rsurface.batchelement3i_bufferoffset = 0;
11617 rsurface.batchelement3s = NULL;
11618 rsurface.batchelement3s_indexbuffer = NULL;
11619 rsurface.batchelement3s_bufferoffset = 0;
11620 if (endvertex <= 65536)
11622 rsurface.batchelement3s = rsurface.array_batchelement3s;
11623 for (i = 0;i < numtriangles*3;i++)
11624 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11626 rsurface.batchfirsttriangle = firsttriangle;
11627 rsurface.batchnumtriangles = numtriangles;
11632 // something needs software processing, do it for real...
11633 // we only directly handle interleaved array data in this case...
11634 rsurface.batchgeneratedvertex = true;
11636 // now copy the vertex data into a combined array and make an index array
11637 // (this is what Quake3 does all the time)
11638 //if (gaps || rsurface.batchfirstvertex)
11640 rsurface.batchvertexposition = NULL;
11641 rsurface.batchvertexpositionbuffer = NULL;
11642 rsurface.batchvertexmesh = NULL;
11643 rsurface.batchvertexmeshbuffer = NULL;
11644 rsurface.batchvertex3f = NULL;
11645 rsurface.batchvertex3f_vertexbuffer = NULL;
11646 rsurface.batchvertex3f_bufferoffset = 0;
11647 rsurface.batchsvector3f = NULL;
11648 rsurface.batchsvector3f_vertexbuffer = NULL;
11649 rsurface.batchsvector3f_bufferoffset = 0;
11650 rsurface.batchtvector3f = NULL;
11651 rsurface.batchtvector3f_vertexbuffer = NULL;
11652 rsurface.batchtvector3f_bufferoffset = 0;
11653 rsurface.batchnormal3f = NULL;
11654 rsurface.batchnormal3f_vertexbuffer = NULL;
11655 rsurface.batchnormal3f_bufferoffset = 0;
11656 rsurface.batchlightmapcolor4f = NULL;
11657 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11658 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11659 rsurface.batchtexcoordtexture2f = NULL;
11660 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11661 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11662 rsurface.batchtexcoordlightmap2f = NULL;
11663 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11664 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11665 rsurface.batchelement3i = rsurface.array_batchelement3i;
11666 rsurface.batchelement3i_indexbuffer = NULL;
11667 rsurface.batchelement3i_bufferoffset = 0;
11668 rsurface.batchelement3s = NULL;
11669 rsurface.batchelement3s_indexbuffer = NULL;
11670 rsurface.batchelement3s_bufferoffset = 0;
11671 // we'll only be setting up certain arrays as needed
11672 if (batchneed & BATCHNEED_VERTEXPOSITION)
11673 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11674 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11675 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11676 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11677 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11678 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11679 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11680 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11682 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11683 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11685 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11686 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11687 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11688 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11689 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11690 rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
11693 for (i = 0;i < texturenumsurfaces;i++)
11695 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11696 surfacenumvertices = texturesurfacelist[i]->num_vertices;
11697 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11698 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11699 // copy only the data requested
11700 if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
11701 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
11702 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11703 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11704 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11706 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11707 memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11708 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11709 memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11710 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11712 memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11713 memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11715 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11716 memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11717 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11718 memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11719 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11720 memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11722 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11723 numvertices += surfacenumvertices;
11724 numtriangles += surfacenumtriangles;
11727 // generate a 16bit index array as well if possible
11728 // (in general, dynamic batches fit)
11729 if (numvertices <= 65536)
11731 rsurface.batchelement3s = rsurface.array_batchelement3s;
11732 for (i = 0;i < numtriangles*3;i++)
11733 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11736 // since we've copied everything, the batch now starts at 0
11737 rsurface.batchfirstvertex = 0;
11738 rsurface.batchnumvertices = numvertices;
11739 rsurface.batchfirsttriangle = 0;
11740 rsurface.batchnumtriangles = numtriangles;
11743 // q1bsp surfaces rendered in vertex color mode have to have colors
11744 // calculated based on lightstyles
11745 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11747 // generate color arrays for the surfaces in this list
11751 const int *offsets;
11752 const unsigned char *lm;
11754 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11755 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11756 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11757 for (i = 0;i < texturenumsurfaces;i++)
11759 surface = texturesurfacelist[i];
11760 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11761 surfacenumvertices = surface->num_vertices;
11762 if (surface->lightmapinfo->samples)
11764 for (j = 0;j < surfacenumvertices;j++)
11766 lm = surface->lightmapinfo->samples + offsets[j];
11767 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11768 VectorScale(lm, scale, c);
11769 if (surface->lightmapinfo->styles[1] != 255)
11771 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11773 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11774 VectorMA(c, scale, lm, c);
11775 if (surface->lightmapinfo->styles[2] != 255)
11778 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11779 VectorMA(c, scale, lm, c);
11780 if (surface->lightmapinfo->styles[3] != 255)
11783 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11784 VectorMA(c, scale, lm, c);
11791 Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, min(c[0], 255) * (1.0f / 255.0f), min(c[1], 255) * (1.0f / 255.0f), min(c[2], 255) * (1.0f / 255.0f), 1);
11797 for (j = 0;j < surfacenumvertices;j++)
11799 Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11806 // if vertices are deformed (sprite flares and things in maps, possibly
11807 // water waves, bulges and other deformations), modify the copied vertices
11809 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11811 switch (deform->deform)
11814 case Q3DEFORM_PROJECTIONSHADOW:
11815 case Q3DEFORM_TEXT0:
11816 case Q3DEFORM_TEXT1:
11817 case Q3DEFORM_TEXT2:
11818 case Q3DEFORM_TEXT3:
11819 case Q3DEFORM_TEXT4:
11820 case Q3DEFORM_TEXT5:
11821 case Q3DEFORM_TEXT6:
11822 case Q3DEFORM_TEXT7:
11823 case Q3DEFORM_NONE:
11825 case Q3DEFORM_AUTOSPRITE:
11826 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11827 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11828 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11829 VectorNormalize(newforward);
11830 VectorNormalize(newright);
11831 VectorNormalize(newup);
11832 // a single autosprite surface can contain multiple sprites...
11833 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11835 VectorClear(center);
11836 for (i = 0;i < 4;i++)
11837 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11838 VectorScale(center, 0.25f, center);
11839 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11840 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11841 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11842 for (i = 0;i < 4;i++)
11844 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11845 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
11848 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11849 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11850 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
11851 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11852 rsurface.batchvertex3f_vertexbuffer = NULL;
11853 rsurface.batchvertex3f_bufferoffset = 0;
11854 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11855 rsurface.batchsvector3f_vertexbuffer = NULL;
11856 rsurface.batchsvector3f_bufferoffset = 0;
11857 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11858 rsurface.batchtvector3f_vertexbuffer = NULL;
11859 rsurface.batchtvector3f_bufferoffset = 0;
11860 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11861 rsurface.batchnormal3f_vertexbuffer = NULL;
11862 rsurface.batchnormal3f_bufferoffset = 0;
11864 case Q3DEFORM_AUTOSPRITE2:
11865 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11866 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11867 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11868 VectorNormalize(newforward);
11869 VectorNormalize(newright);
11870 VectorNormalize(newup);
11872 const float *v1, *v2;
11882 memset(shortest, 0, sizeof(shortest));
11883 // a single autosprite surface can contain multiple sprites...
11884 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11886 VectorClear(center);
11887 for (i = 0;i < 4;i++)
11888 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11889 VectorScale(center, 0.25f, center);
11890 // find the two shortest edges, then use them to define the
11891 // axis vectors for rotating around the central axis
11892 for (i = 0;i < 6;i++)
11894 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11895 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11896 l = VectorDistance2(v1, v2);
11897 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11898 if (v1[2] != v2[2])
11899 l += (1.0f / 1024.0f);
11900 if (shortest[0].length2 > l || i == 0)
11902 shortest[1] = shortest[0];
11903 shortest[0].length2 = l;
11904 shortest[0].v1 = v1;
11905 shortest[0].v2 = v2;
11907 else if (shortest[1].length2 > l || i == 1)
11909 shortest[1].length2 = l;
11910 shortest[1].v1 = v1;
11911 shortest[1].v2 = v2;
11914 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11915 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11916 // this calculates the right vector from the shortest edge
11917 // and the up vector from the edge midpoints
11918 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11919 VectorNormalize(right);
11920 VectorSubtract(end, start, up);
11921 VectorNormalize(up);
11922 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11923 VectorSubtract(rsurface.localvieworigin, center, forward);
11924 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11925 VectorNegate(forward, forward);
11926 VectorReflect(forward, 0, up, forward);
11927 VectorNormalize(forward);
11928 CrossProduct(up, forward, newright);
11929 VectorNormalize(newright);
11930 // rotate the quad around the up axis vector, this is made
11931 // especially easy by the fact we know the quad is flat,
11932 // so we only have to subtract the center position and
11933 // measure distance along the right vector, and then
11934 // multiply that by the newright vector and add back the
11936 // we also need to subtract the old position to undo the
11937 // displacement from the center, which we do with a
11938 // DotProduct, the subtraction/addition of center is also
11939 // optimized into DotProducts here
11940 l = DotProduct(right, center);
11941 for (i = 0;i < 4;i++)
11943 v1 = rsurface.batchvertex3f + 3*(j+i);
11944 f = DotProduct(right, v1) - l;
11945 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
11949 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11950 rsurface.batchvertex3f_vertexbuffer = NULL;
11951 rsurface.batchvertex3f_bufferoffset = 0;
11952 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11954 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11955 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11956 rsurface.batchnormal3f_vertexbuffer = NULL;
11957 rsurface.batchnormal3f_bufferoffset = 0;
11959 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11961 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
11962 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11963 rsurface.batchsvector3f_vertexbuffer = NULL;
11964 rsurface.batchsvector3f_bufferoffset = 0;
11965 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11966 rsurface.batchtvector3f_vertexbuffer = NULL;
11967 rsurface.batchtvector3f_bufferoffset = 0;
11970 case Q3DEFORM_NORMAL:
11971 // deform the normals to make reflections wavey
11972 for (j = 0;j < rsurface.batchnumvertices;j++)
11975 float *normal = rsurface.array_batchnormal3f + 3*j;
11976 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11977 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11978 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]);
11979 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]);
11980 VectorNormalize(normal);
11982 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11983 rsurface.batchnormal3f_vertexbuffer = NULL;
11984 rsurface.batchnormal3f_bufferoffset = 0;
11985 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11987 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
11988 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11989 rsurface.batchsvector3f_vertexbuffer = NULL;
11990 rsurface.batchsvector3f_bufferoffset = 0;
11991 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11992 rsurface.batchtvector3f_vertexbuffer = NULL;
11993 rsurface.batchtvector3f_bufferoffset = 0;
11996 case Q3DEFORM_WAVE:
11997 // deform vertex array to make wavey water and flags and such
11998 waveparms[0] = deform->waveparms[0];
11999 waveparms[1] = deform->waveparms[1];
12000 waveparms[2] = deform->waveparms[2];
12001 waveparms[3] = deform->waveparms[3];
12002 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
12003 break; // if wavefunc is a nop, don't make a dynamic vertex array
12004 // this is how a divisor of vertex influence on deformation
12005 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
12006 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
12007 for (j = 0;j < rsurface.batchnumvertices;j++)
12009 // if the wavefunc depends on time, evaluate it per-vertex
12012 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
12013 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
12015 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
12017 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12018 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
12019 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12020 rsurface.batchvertex3f_vertexbuffer = NULL;
12021 rsurface.batchvertex3f_bufferoffset = 0;
12022 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
12023 rsurface.batchnormal3f_vertexbuffer = NULL;
12024 rsurface.batchnormal3f_bufferoffset = 0;
12025 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12027 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
12028 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
12029 rsurface.batchsvector3f_vertexbuffer = NULL;
12030 rsurface.batchsvector3f_bufferoffset = 0;
12031 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
12032 rsurface.batchtvector3f_vertexbuffer = NULL;
12033 rsurface.batchtvector3f_bufferoffset = 0;
12036 case Q3DEFORM_BULGE:
12037 // deform vertex array to make the surface have moving bulges
12038 for (j = 0;j < rsurface.batchnumvertices;j++)
12040 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
12041 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
12043 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12044 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
12045 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12046 rsurface.batchvertex3f_vertexbuffer = NULL;
12047 rsurface.batchvertex3f_bufferoffset = 0;
12048 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
12049 rsurface.batchnormal3f_vertexbuffer = NULL;
12050 rsurface.batchnormal3f_bufferoffset = 0;
12051 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12053 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
12054 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
12055 rsurface.batchsvector3f_vertexbuffer = NULL;
12056 rsurface.batchsvector3f_bufferoffset = 0;
12057 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
12058 rsurface.batchtvector3f_vertexbuffer = NULL;
12059 rsurface.batchtvector3f_bufferoffset = 0;
12062 case Q3DEFORM_MOVE:
12063 // deform vertex array
12064 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
12065 break; // if wavefunc is a nop, don't make a dynamic vertex array
12066 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
12067 VectorScale(deform->parms, scale, waveparms);
12068 for (j = 0;j < rsurface.batchnumvertices;j++)
12069 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
12070 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12071 rsurface.batchvertex3f_vertexbuffer = NULL;
12072 rsurface.batchvertex3f_bufferoffset = 0;
12077 // generate texcoords based on the chosen texcoord source
12078 switch(rsurface.texture->tcgen.tcgen)
12081 case Q3TCGEN_TEXTURE:
12083 case Q3TCGEN_LIGHTMAP:
12084 if (rsurface.batchtexcoordlightmap2f)
12085 memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
12086 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12087 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12088 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12090 case Q3TCGEN_VECTOR:
12091 for (j = 0;j < rsurface.batchnumvertices;j++)
12093 rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
12094 rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
12096 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12097 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12098 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12100 case Q3TCGEN_ENVIRONMENT:
12101 // make environment reflections using a spheremap
12102 for (j = 0;j < rsurface.batchnumvertices;j++)
12104 // identical to Q3A's method, but executed in worldspace so
12105 // carried models can be shiny too
12107 float viewer[3], d, reflected[3], worldreflected[3];
12109 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
12110 // VectorNormalize(viewer);
12112 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
12114 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
12115 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
12116 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
12117 // note: this is proportinal to viewer, so we can normalize later
12119 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
12120 VectorNormalize(worldreflected);
12122 // note: this sphere map only uses world x and z!
12123 // so positive and negative y will LOOK THE SAME.
12124 rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
12125 rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
12127 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12128 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12129 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12132 // the only tcmod that needs software vertex processing is turbulent, so
12133 // check for it here and apply the changes if needed
12134 // and we only support that as the first one
12135 // (handling a mixture of turbulent and other tcmods would be problematic
12136 // without punting it entirely to a software path)
12137 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
12139 amplitude = rsurface.texture->tcmods[0].parms[1];
12140 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
12141 for (j = 0;j < rsurface.batchnumvertices;j++)
12143 rsurface.array_batchtexcoordtexture2f[j*2+0] += amplitude * sin(((rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12144 rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12146 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12147 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12148 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12151 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
12153 // convert the modified arrays to vertex structs
12154 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
12155 rsurface.batchvertexmeshbuffer = NULL;
12156 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
12157 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12158 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
12159 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
12160 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12161 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
12162 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
12164 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12166 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
12167 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
12170 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
12171 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12172 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
12173 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
12174 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12175 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
12176 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
12177 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12178 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
12181 if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
12183 // convert the modified arrays to vertex structs
12184 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
12185 rsurface.batchvertexpositionbuffer = NULL;
12186 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
12187 memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
12189 for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
12190 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
12194 void RSurf_DrawBatch(void)
12196 // sometimes a zero triangle surface (usually a degenerate patch) makes it
12197 // through the pipeline, killing it earlier in the pipeline would have
12198 // per-surface overhead rather than per-batch overhead, so it's best to
12199 // reject it here, before it hits glDraw.
12200 if (rsurface.batchnumtriangles == 0)
12203 // batch debugging code
12204 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
12210 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
12211 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
12214 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
12216 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
12218 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
12219 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);
12226 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);
12229 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
12231 // pick the closest matching water plane
12232 int planeindex, vertexindex, bestplaneindex = -1;
12236 r_waterstate_waterplane_t *p;
12238 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
12240 if(p->camera_entity != rsurface.texture->camera_entity)
12243 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
12244 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
12246 Matrix4x4_Transform(&rsurface.matrix, v, vert);
12247 d += fabs(PlaneDiff(vert, &p->plane));
12249 if (bestd > d || bestplaneindex < 0)
12252 bestplaneindex = planeindex;
12255 return bestplaneindex;
12258 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
12261 for (i = 0;i < rsurface.batchnumvertices;i++)
12262 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
12263 rsurface.passcolor4f = rsurface.array_passcolor4f;
12264 rsurface.passcolor4f_vertexbuffer = 0;
12265 rsurface.passcolor4f_bufferoffset = 0;
12268 static void RSurf_DrawBatch_GL11_ApplyFog(void)
12275 if (rsurface.passcolor4f)
12277 // generate color arrays
12278 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
12280 f = RSurf_FogVertex(v);
12289 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
12291 f = RSurf_FogVertex(v);
12298 rsurface.passcolor4f = rsurface.array_passcolor4f;
12299 rsurface.passcolor4f_vertexbuffer = 0;
12300 rsurface.passcolor4f_bufferoffset = 0;
12303 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
12310 if (!rsurface.passcolor4f)
12312 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
12314 f = RSurf_FogVertex(v);
12315 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
12316 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
12317 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
12320 rsurface.passcolor4f = rsurface.array_passcolor4f;
12321 rsurface.passcolor4f_vertexbuffer = 0;
12322 rsurface.passcolor4f_bufferoffset = 0;
12325 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
12330 if (!rsurface.passcolor4f)
12332 for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12339 rsurface.passcolor4f = rsurface.array_passcolor4f;
12340 rsurface.passcolor4f_vertexbuffer = 0;
12341 rsurface.passcolor4f_bufferoffset = 0;
12344 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12349 if (!rsurface.passcolor4f)
12351 for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12353 c2[0] = c[0] + r_refdef.scene.ambient;
12354 c2[1] = c[1] + r_refdef.scene.ambient;
12355 c2[2] = c[2] + r_refdef.scene.ambient;
12358 rsurface.passcolor4f = rsurface.array_passcolor4f;
12359 rsurface.passcolor4f_vertexbuffer = 0;
12360 rsurface.passcolor4f_bufferoffset = 0;
12363 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12366 rsurface.passcolor4f = NULL;
12367 rsurface.passcolor4f_vertexbuffer = 0;
12368 rsurface.passcolor4f_bufferoffset = 0;
12369 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12370 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12371 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12372 GL_Color(r, g, b, a);
12373 R_Mesh_TexBind(0, rsurface.lightmaptexture);
12377 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12379 // TODO: optimize applyfog && applycolor case
12380 // just apply fog if necessary, and tint the fog color array if necessary
12381 rsurface.passcolor4f = NULL;
12382 rsurface.passcolor4f_vertexbuffer = 0;
12383 rsurface.passcolor4f_bufferoffset = 0;
12384 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12385 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12386 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12387 GL_Color(r, g, b, a);
12391 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12394 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12395 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12396 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12397 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12398 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12399 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12400 GL_Color(r, g, b, a);
12404 static void RSurf_DrawBatch_GL11_ClampColor(void)
12409 if (!rsurface.passcolor4f)
12411 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12413 c2[0] = bound(0.0f, c1[0], 1.0f);
12414 c2[1] = bound(0.0f, c1[1], 1.0f);
12415 c2[2] = bound(0.0f, c1[2], 1.0f);
12416 c2[3] = bound(0.0f, c1[3], 1.0f);
12420 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
12430 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
12432 f = -DotProduct(r_refdef.view.forward, n);
12434 f = f * 0.85 + 0.15; // work around so stuff won't get black
12435 f *= r_refdef.lightmapintensity;
12436 Vector4Set(c, f, f, f, 1);
12439 rsurface.passcolor4f = rsurface.array_passcolor4f;
12440 rsurface.passcolor4f_vertexbuffer = 0;
12441 rsurface.passcolor4f_bufferoffset = 0;
12444 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12446 RSurf_DrawBatch_GL11_ApplyFakeLight();
12447 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12448 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12449 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12450 GL_Color(r, g, b, a);
12454 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12462 vec3_t ambientcolor;
12463 vec3_t diffusecolor;
12467 VectorCopy(rsurface.modellight_lightdir, lightdir);
12468 f = 0.5f * r_refdef.lightmapintensity;
12469 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12470 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12471 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12472 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12473 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12474 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12476 if (VectorLength2(diffusecolor) > 0)
12478 // q3-style directional shading
12479 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
12481 if ((f = DotProduct(n, lightdir)) > 0)
12482 VectorMA(ambientcolor, f, diffusecolor, c);
12484 VectorCopy(ambientcolor, c);
12491 rsurface.passcolor4f = rsurface.array_passcolor4f;
12492 rsurface.passcolor4f_vertexbuffer = 0;
12493 rsurface.passcolor4f_bufferoffset = 0;
12494 *applycolor = false;
12498 *r = ambientcolor[0];
12499 *g = ambientcolor[1];
12500 *b = ambientcolor[2];
12501 rsurface.passcolor4f = NULL;
12502 rsurface.passcolor4f_vertexbuffer = 0;
12503 rsurface.passcolor4f_bufferoffset = 0;
12507 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12509 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12510 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12511 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12512 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12513 GL_Color(r, g, b, a);
12517 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12523 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12525 f = 1 - RSurf_FogVertex(v);
12533 void RSurf_SetupDepthAndCulling(void)
12535 // submodels are biased to avoid z-fighting with world surfaces that they
12536 // may be exactly overlapping (avoids z-fighting artifacts on certain
12537 // doors and things in Quake maps)
12538 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12539 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12540 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12541 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12544 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12546 // transparent sky would be ridiculous
12547 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12549 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12550 skyrenderlater = true;
12551 RSurf_SetupDepthAndCulling();
12552 GL_DepthMask(true);
12553 // LordHavoc: HalfLife maps have freaky skypolys so don't use
12554 // skymasking on them, and Quake3 never did sky masking (unlike
12555 // software Quake and software Quake2), so disable the sky masking
12556 // in Quake3 maps as it causes problems with q3map2 sky tricks,
12557 // and skymasking also looks very bad when noclipping outside the
12558 // level, so don't use it then either.
12559 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12561 R_Mesh_ResetTextureState();
12562 if (skyrendermasked)
12564 R_SetupShader_DepthOrShadow();
12565 // depth-only (masking)
12566 GL_ColorMask(0,0,0,0);
12567 // just to make sure that braindead drivers don't draw
12568 // anything despite that colormask...
12569 GL_BlendFunc(GL_ZERO, GL_ONE);
12570 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12571 R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12575 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12577 GL_BlendFunc(GL_ONE, GL_ZERO);
12578 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12579 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12580 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12583 if (skyrendermasked)
12584 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12586 R_Mesh_ResetTextureState();
12587 GL_Color(1, 1, 1, 1);
12590 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12591 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12592 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12594 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12598 // render screenspace normalmap to texture
12599 GL_DepthMask(true);
12600 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12605 // bind lightmap texture
12607 // water/refraction/reflection/camera surfaces have to be handled specially
12608 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)) && !r_waterstate.renderingscene)
12610 int start, end, startplaneindex;
12611 for (start = 0;start < texturenumsurfaces;start = end)
12613 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12614 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12616 // now that we have a batch using the same planeindex, render it
12617 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
12619 // render water or distortion background
12620 GL_DepthMask(true);
12621 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));
12623 // blend surface on top
12624 GL_DepthMask(false);
12625 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12628 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) && !r_waterstate.renderingscene)
12630 // render surface with reflection texture as input
12631 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12632 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));
12639 // render surface batch normally
12640 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12641 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12645 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12647 // OpenGL 1.3 path - anything not completely ancient
12648 qboolean applycolor;
12651 const texturelayer_t *layer;
12652 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);
12653 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12655 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12658 int layertexrgbscale;
12659 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12661 if (layerindex == 0)
12662 GL_AlphaTest(true);
12665 GL_AlphaTest(false);
12666 GL_DepthFunc(GL_EQUAL);
12669 GL_DepthMask(layer->depthmask && writedepth);
12670 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12671 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12673 layertexrgbscale = 4;
12674 VectorScale(layer->color, 0.25f, layercolor);
12676 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12678 layertexrgbscale = 2;
12679 VectorScale(layer->color, 0.5f, layercolor);
12683 layertexrgbscale = 1;
12684 VectorScale(layer->color, 1.0f, layercolor);
12686 layercolor[3] = layer->color[3];
12687 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12688 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12689 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12690 switch (layer->type)
12692 case TEXTURELAYERTYPE_LITTEXTURE:
12693 // single-pass lightmapped texture with 2x rgbscale
12694 R_Mesh_TexBind(0, r_texture_white);
12695 R_Mesh_TexMatrix(0, NULL);
12696 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12697 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12698 R_Mesh_TexBind(1, layer->texture);
12699 R_Mesh_TexMatrix(1, &layer->texmatrix);
12700 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12701 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12702 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12703 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12704 else if (FAKELIGHT_ENABLED)
12705 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12706 else if (rsurface.uselightmaptexture)
12707 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12709 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12711 case TEXTURELAYERTYPE_TEXTURE:
12712 // singletexture unlit texture with transparency support
12713 R_Mesh_TexBind(0, layer->texture);
12714 R_Mesh_TexMatrix(0, &layer->texmatrix);
12715 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12716 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12717 R_Mesh_TexBind(1, 0);
12718 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12719 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12721 case TEXTURELAYERTYPE_FOG:
12722 // singletexture fogging
12723 if (layer->texture)
12725 R_Mesh_TexBind(0, layer->texture);
12726 R_Mesh_TexMatrix(0, &layer->texmatrix);
12727 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12728 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12732 R_Mesh_TexBind(0, 0);
12733 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12735 R_Mesh_TexBind(1, 0);
12736 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12737 // generate a color array for the fog pass
12738 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12739 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12743 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12746 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12748 GL_DepthFunc(GL_LEQUAL);
12749 GL_AlphaTest(false);
12753 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12755 // OpenGL 1.1 - crusty old voodoo path
12758 const texturelayer_t *layer;
12759 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);
12760 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12762 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12764 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12766 if (layerindex == 0)
12767 GL_AlphaTest(true);
12770 GL_AlphaTest(false);
12771 GL_DepthFunc(GL_EQUAL);
12774 GL_DepthMask(layer->depthmask && writedepth);
12775 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12776 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12777 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12778 switch (layer->type)
12780 case TEXTURELAYERTYPE_LITTEXTURE:
12781 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12783 // two-pass lit texture with 2x rgbscale
12784 // first the lightmap pass
12785 R_Mesh_TexBind(0, r_texture_white);
12786 R_Mesh_TexMatrix(0, NULL);
12787 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12788 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12789 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12790 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12791 else if (FAKELIGHT_ENABLED)
12792 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12793 else if (rsurface.uselightmaptexture)
12794 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12796 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12797 // then apply the texture to it
12798 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12799 R_Mesh_TexBind(0, layer->texture);
12800 R_Mesh_TexMatrix(0, &layer->texmatrix);
12801 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12802 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12803 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);
12807 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12808 R_Mesh_TexBind(0, layer->texture);
12809 R_Mesh_TexMatrix(0, &layer->texmatrix);
12810 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12811 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12812 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12813 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);
12815 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);
12818 case TEXTURELAYERTYPE_TEXTURE:
12819 // singletexture unlit texture with transparency support
12820 R_Mesh_TexBind(0, layer->texture);
12821 R_Mesh_TexMatrix(0, &layer->texmatrix);
12822 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12823 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12824 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);
12826 case TEXTURELAYERTYPE_FOG:
12827 // singletexture fogging
12828 if (layer->texture)
12830 R_Mesh_TexBind(0, layer->texture);
12831 R_Mesh_TexMatrix(0, &layer->texmatrix);
12832 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12833 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12837 R_Mesh_TexBind(0, 0);
12838 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12840 // generate a color array for the fog pass
12841 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12842 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12846 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12849 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12851 GL_DepthFunc(GL_LEQUAL);
12852 GL_AlphaTest(false);
12856 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12860 r_vertexgeneric_t *batchvertex;
12863 GL_AlphaTest(false);
12864 // R_Mesh_ResetTextureState();
12865 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12867 if(rsurface.texture && rsurface.texture->currentskinframe)
12869 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12870 c[3] *= rsurface.texture->currentalpha;
12880 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12882 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12883 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12884 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12887 // brighten it up (as texture value 127 means "unlit")
12888 c[0] *= 2 * r_refdef.view.colorscale;
12889 c[1] *= 2 * r_refdef.view.colorscale;
12890 c[2] *= 2 * r_refdef.view.colorscale;
12892 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12893 c[3] *= r_wateralpha.value;
12895 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12897 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12898 GL_DepthMask(false);
12900 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12902 GL_BlendFunc(GL_ONE, GL_ONE);
12903 GL_DepthMask(false);
12905 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12907 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12908 GL_DepthMask(false);
12910 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12912 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12913 GL_DepthMask(false);
12917 GL_BlendFunc(GL_ONE, GL_ZERO);
12918 GL_DepthMask(writedepth);
12921 if (r_showsurfaces.integer == 3)
12923 rsurface.passcolor4f = NULL;
12925 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12927 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12929 rsurface.passcolor4f = NULL;
12930 rsurface.passcolor4f_vertexbuffer = 0;
12931 rsurface.passcolor4f_bufferoffset = 0;
12933 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12935 qboolean applycolor = true;
12938 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12940 r_refdef.lightmapintensity = 1;
12941 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12942 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12944 else if (FAKELIGHT_ENABLED)
12946 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12948 r_refdef.lightmapintensity = r_fakelight_intensity.value;
12949 RSurf_DrawBatch_GL11_ApplyFakeLight();
12950 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12954 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12956 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12957 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12958 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12961 if(!rsurface.passcolor4f)
12962 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12964 RSurf_DrawBatch_GL11_ApplyAmbient();
12965 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12966 if(r_refdef.fogenabled)
12967 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12968 RSurf_DrawBatch_GL11_ClampColor();
12970 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12971 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12974 else if (!r_refdef.view.showdebug)
12976 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12977 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12978 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12980 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12981 Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12983 R_Mesh_PrepareVertices_Generic_Unlock();
12986 else if (r_showsurfaces.integer == 4)
12988 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12989 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12990 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12992 unsigned char c = vi << 3;
12993 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12994 Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12996 R_Mesh_PrepareVertices_Generic_Unlock();
12999 else if (r_showsurfaces.integer == 2)
13002 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13003 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
13004 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
13006 unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
13007 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
13008 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
13009 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
13010 Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
13011 Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
13012 Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
13014 R_Mesh_PrepareVertices_Generic_Unlock();
13015 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
13019 int texturesurfaceindex;
13021 const msurface_t *surface;
13022 unsigned char surfacecolor4ub[4];
13023 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13024 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
13026 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
13028 surface = texturesurfacelist[texturesurfaceindex];
13029 k = (int)(((size_t)surface) / sizeof(msurface_t));
13030 Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
13031 for (j = 0;j < surface->num_vertices;j++)
13033 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13034 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
13038 R_Mesh_PrepareVertices_Generic_Unlock();
13043 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13046 RSurf_SetupDepthAndCulling();
13047 if (r_showsurfaces.integer)
13049 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13052 switch (vid.renderpath)
13054 case RENDERPATH_GL20:
13055 case RENDERPATH_CGGL:
13056 case RENDERPATH_D3D9:
13057 case RENDERPATH_D3D10:
13058 case RENDERPATH_D3D11:
13059 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13061 case RENDERPATH_GL13:
13062 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13064 case RENDERPATH_GL11:
13065 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13071 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13074 RSurf_SetupDepthAndCulling();
13075 if (r_showsurfaces.integer)
13077 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13080 switch (vid.renderpath)
13082 case RENDERPATH_GL20:
13083 case RENDERPATH_CGGL:
13084 case RENDERPATH_D3D9:
13085 case RENDERPATH_D3D10:
13086 case RENDERPATH_D3D11:
13087 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13089 case RENDERPATH_GL13:
13090 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13092 case RENDERPATH_GL11:
13093 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13099 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13102 int texturenumsurfaces, endsurface;
13103 texture_t *texture;
13104 const msurface_t *surface;
13105 #define MAXBATCH_TRANSPARENTSURFACES 256
13106 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
13108 // if the model is static it doesn't matter what value we give for
13109 // wantnormals and wanttangents, so this logic uses only rules applicable
13110 // to a model, knowing that they are meaningless otherwise
13111 if (ent == r_refdef.scene.worldentity)
13112 RSurf_ActiveWorldEntity();
13113 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13114 RSurf_ActiveModelEntity(ent, false, false, false);
13117 switch (vid.renderpath)
13119 case RENDERPATH_GL20:
13120 case RENDERPATH_CGGL:
13121 case RENDERPATH_D3D9:
13122 case RENDERPATH_D3D10:
13123 case RENDERPATH_D3D11:
13124 RSurf_ActiveModelEntity(ent, true, true, false);
13126 case RENDERPATH_GL13:
13127 case RENDERPATH_GL11:
13128 RSurf_ActiveModelEntity(ent, true, false, false);
13133 if (r_transparentdepthmasking.integer)
13135 qboolean setup = false;
13136 for (i = 0;i < numsurfaces;i = j)
13139 surface = rsurface.modelsurfaces + surfacelist[i];
13140 texture = surface->texture;
13141 rsurface.texture = R_GetCurrentTexture(texture);
13142 rsurface.lightmaptexture = NULL;
13143 rsurface.deluxemaptexture = NULL;
13144 rsurface.uselightmaptexture = false;
13145 // scan ahead until we find a different texture
13146 endsurface = min(i + 1024, numsurfaces);
13147 texturenumsurfaces = 0;
13148 texturesurfacelist[texturenumsurfaces++] = surface;
13149 for (;j < endsurface;j++)
13151 surface = rsurface.modelsurfaces + surfacelist[j];
13152 if (texture != surface->texture)
13154 texturesurfacelist[texturenumsurfaces++] = surface;
13156 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
13158 // render the range of surfaces as depth
13162 GL_ColorMask(0,0,0,0);
13164 GL_DepthTest(true);
13165 GL_BlendFunc(GL_ONE, GL_ZERO);
13166 GL_DepthMask(true);
13167 GL_AlphaTest(false);
13168 // R_Mesh_ResetTextureState();
13169 R_SetupShader_DepthOrShadow();
13171 RSurf_SetupDepthAndCulling();
13172 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13173 R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13177 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
13180 for (i = 0;i < numsurfaces;i = j)
13183 surface = rsurface.modelsurfaces + surfacelist[i];
13184 texture = surface->texture;
13185 rsurface.texture = R_GetCurrentTexture(texture);
13186 // scan ahead until we find a different texture
13187 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
13188 texturenumsurfaces = 0;
13189 texturesurfacelist[texturenumsurfaces++] = surface;
13190 if(FAKELIGHT_ENABLED)
13192 rsurface.lightmaptexture = NULL;
13193 rsurface.deluxemaptexture = NULL;
13194 rsurface.uselightmaptexture = false;
13195 for (;j < endsurface;j++)
13197 surface = rsurface.modelsurfaces + surfacelist[j];
13198 if (texture != surface->texture)
13200 texturesurfacelist[texturenumsurfaces++] = surface;
13205 rsurface.lightmaptexture = surface->lightmaptexture;
13206 rsurface.deluxemaptexture = surface->deluxemaptexture;
13207 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
13208 for (;j < endsurface;j++)
13210 surface = rsurface.modelsurfaces + surfacelist[j];
13211 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
13213 texturesurfacelist[texturenumsurfaces++] = surface;
13216 // render the range of surfaces
13217 if (ent == r_refdef.scene.worldentity)
13218 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13220 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13222 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13223 GL_AlphaTest(false);
13226 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
13228 // transparent surfaces get pushed off into the transparent queue
13229 int surfacelistindex;
13230 const msurface_t *surface;
13231 vec3_t tempcenter, center;
13232 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
13234 surface = texturesurfacelist[surfacelistindex];
13235 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
13236 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
13237 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
13238 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
13239 if (queueentity->transparent_offset) // transparent offset
13241 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
13242 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
13243 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
13245 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
13249 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
13251 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
13253 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
13255 RSurf_SetupDepthAndCulling();
13256 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13257 R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13261 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
13263 const entity_render_t *queueentity = r_refdef.scene.worldentity;
13266 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13269 if (!rsurface.texture->currentnumlayers)
13271 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13272 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13274 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13276 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13277 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13278 else if (!rsurface.texture->currentnumlayers)
13280 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13282 // in the deferred case, transparent surfaces were queued during prepass
13283 if (!r_shadow_usingdeferredprepass)
13284 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13288 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13289 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13294 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13297 texture_t *texture;
13298 // break the surface list down into batches by texture and use of lightmapping
13299 for (i = 0;i < numsurfaces;i = j)
13302 // texture is the base texture pointer, rsurface.texture is the
13303 // current frame/skin the texture is directing us to use (for example
13304 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13305 // use skin 1 instead)
13306 texture = surfacelist[i]->texture;
13307 rsurface.texture = R_GetCurrentTexture(texture);
13308 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13310 // if this texture is not the kind we want, skip ahead to the next one
13311 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13315 if(FAKELIGHT_ENABLED || depthonly || prepass)
13317 rsurface.lightmaptexture = NULL;
13318 rsurface.deluxemaptexture = NULL;
13319 rsurface.uselightmaptexture = false;
13320 // simply scan ahead until we find a different texture or lightmap state
13321 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13326 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13327 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13328 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13329 // simply scan ahead until we find a different texture or lightmap state
13330 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13333 // render the range of surfaces
13334 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
13338 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
13342 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13345 if (!rsurface.texture->currentnumlayers)
13347 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13348 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13350 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13352 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13353 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13354 else if (!rsurface.texture->currentnumlayers)
13356 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13358 // in the deferred case, transparent surfaces were queued during prepass
13359 if (!r_shadow_usingdeferredprepass)
13360 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13364 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13365 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13370 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13373 texture_t *texture;
13374 // break the surface list down into batches by texture and use of lightmapping
13375 for (i = 0;i < numsurfaces;i = j)
13378 // texture is the base texture pointer, rsurface.texture is the
13379 // current frame/skin the texture is directing us to use (for example
13380 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13381 // use skin 1 instead)
13382 texture = surfacelist[i]->texture;
13383 rsurface.texture = R_GetCurrentTexture(texture);
13384 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13386 // if this texture is not the kind we want, skip ahead to the next one
13387 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13391 if(FAKELIGHT_ENABLED || depthonly || prepass)
13393 rsurface.lightmaptexture = NULL;
13394 rsurface.deluxemaptexture = NULL;
13395 rsurface.uselightmaptexture = false;
13396 // simply scan ahead until we find a different texture or lightmap state
13397 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13402 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13403 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13404 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13405 // simply scan ahead until we find a different texture or lightmap state
13406 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13409 // render the range of surfaces
13410 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
13414 float locboxvertex3f[6*4*3] =
13416 1,0,1, 1,0,0, 1,1,0, 1,1,1,
13417 0,1,1, 0,1,0, 0,0,0, 0,0,1,
13418 1,1,1, 1,1,0, 0,1,0, 0,1,1,
13419 0,0,1, 0,0,0, 1,0,0, 1,0,1,
13420 0,0,1, 1,0,1, 1,1,1, 0,1,1,
13421 1,0,0, 0,0,0, 0,1,0, 1,1,0
13424 unsigned short locboxelements[6*2*3] =
13429 12,13,14, 12,14,15,
13430 16,17,18, 16,18,19,
13434 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13437 cl_locnode_t *loc = (cl_locnode_t *)ent;
13439 float vertex3f[6*4*3];
13441 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13442 GL_DepthMask(false);
13443 GL_DepthRange(0, 1);
13444 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13445 GL_DepthTest(true);
13446 GL_CullFace(GL_NONE);
13447 R_EntityMatrix(&identitymatrix);
13449 // R_Mesh_ResetTextureState();
13451 i = surfacelist[0];
13452 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13453 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13454 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13455 surfacelist[0] < 0 ? 0.5f : 0.125f);
13457 if (VectorCompare(loc->mins, loc->maxs))
13459 VectorSet(size, 2, 2, 2);
13460 VectorMA(loc->mins, -0.5f, size, mins);
13464 VectorCopy(loc->mins, mins);
13465 VectorSubtract(loc->maxs, loc->mins, size);
13468 for (i = 0;i < 6*4*3;)
13469 for (j = 0;j < 3;j++, i++)
13470 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13472 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13473 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13474 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13477 void R_DrawLocs(void)
13480 cl_locnode_t *loc, *nearestloc;
13482 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13483 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13485 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13486 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13490 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13492 if (decalsystem->decals)
13493 Mem_Free(decalsystem->decals);
13494 memset(decalsystem, 0, sizeof(*decalsystem));
13497 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)
13500 tridecal_t *decals;
13503 // expand or initialize the system
13504 if (decalsystem->maxdecals <= decalsystem->numdecals)
13506 decalsystem_t old = *decalsystem;
13507 qboolean useshortelements;
13508 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13509 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13510 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)));
13511 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13512 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13513 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13514 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13515 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13516 if (decalsystem->numdecals)
13517 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13519 Mem_Free(old.decals);
13520 for (i = 0;i < decalsystem->maxdecals*3;i++)
13521 decalsystem->element3i[i] = i;
13522 if (useshortelements)
13523 for (i = 0;i < decalsystem->maxdecals*3;i++)
13524 decalsystem->element3s[i] = i;
13527 // grab a decal and search for another free slot for the next one
13528 decals = decalsystem->decals;
13529 decal = decalsystem->decals + (i = decalsystem->freedecal++);
13530 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13532 decalsystem->freedecal = i;
13533 if (decalsystem->numdecals <= i)
13534 decalsystem->numdecals = i + 1;
13536 // initialize the decal
13538 decal->triangleindex = triangleindex;
13539 decal->surfaceindex = surfaceindex;
13540 decal->decalsequence = decalsequence;
13541 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13542 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13543 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13544 decal->color4ub[0][3] = 255;
13545 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13546 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13547 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13548 decal->color4ub[1][3] = 255;
13549 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13550 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13551 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13552 decal->color4ub[2][3] = 255;
13553 decal->vertex3f[0][0] = v0[0];
13554 decal->vertex3f[0][1] = v0[1];
13555 decal->vertex3f[0][2] = v0[2];
13556 decal->vertex3f[1][0] = v1[0];
13557 decal->vertex3f[1][1] = v1[1];
13558 decal->vertex3f[1][2] = v1[2];
13559 decal->vertex3f[2][0] = v2[0];
13560 decal->vertex3f[2][1] = v2[1];
13561 decal->vertex3f[2][2] = v2[2];
13562 decal->texcoord2f[0][0] = t0[0];
13563 decal->texcoord2f[0][1] = t0[1];
13564 decal->texcoord2f[1][0] = t1[0];
13565 decal->texcoord2f[1][1] = t1[1];
13566 decal->texcoord2f[2][0] = t2[0];
13567 decal->texcoord2f[2][1] = t2[1];
13570 extern cvar_t cl_decals_bias;
13571 extern cvar_t cl_decals_models;
13572 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13573 // baseparms, parms, temps
13574 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)
13579 const float *vertex3f;
13581 float points[2][9][3];
13588 e = rsurface.modelelement3i + 3*triangleindex;
13590 vertex3f = rsurface.modelvertex3f;
13592 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13594 index = 3*e[cornerindex];
13595 VectorCopy(vertex3f + index, v[cornerindex]);
13598 //TriangleNormal(v[0], v[1], v[2], normal);
13599 //if (DotProduct(normal, localnormal) < 0.0f)
13601 // clip by each of the box planes formed from the projection matrix
13602 // if anything survives, we emit the decal
13603 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]);
13606 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]);
13609 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]);
13612 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]);
13615 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]);
13618 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]);
13621 // some part of the triangle survived, so we have to accept it...
13624 // dynamic always uses the original triangle
13626 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13628 index = 3*e[cornerindex];
13629 VectorCopy(vertex3f + index, v[cornerindex]);
13632 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13634 // convert vertex positions to texcoords
13635 Matrix4x4_Transform(projection, v[cornerindex], temp);
13636 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13637 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13638 // calculate distance fade from the projection origin
13639 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13640 f = bound(0.0f, f, 1.0f);
13641 c[cornerindex][0] = r * f;
13642 c[cornerindex][1] = g * f;
13643 c[cornerindex][2] = b * f;
13644 c[cornerindex][3] = 1.0f;
13645 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13648 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);
13650 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13651 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);
13653 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)
13655 matrix4x4_t projection;
13656 decalsystem_t *decalsystem;
13659 const msurface_t *surface;
13660 const msurface_t *surfaces;
13661 const int *surfacelist;
13662 const texture_t *texture;
13664 int numsurfacelist;
13665 int surfacelistindex;
13668 float localorigin[3];
13669 float localnormal[3];
13670 float localmins[3];
13671 float localmaxs[3];
13674 float planes[6][4];
13677 int bih_triangles_count;
13678 int bih_triangles[256];
13679 int bih_surfaces[256];
13681 decalsystem = &ent->decalsystem;
13682 model = ent->model;
13683 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13685 R_DecalSystem_Reset(&ent->decalsystem);
13689 if (!model->brush.data_leafs && !cl_decals_models.integer)
13691 if (decalsystem->model)
13692 R_DecalSystem_Reset(decalsystem);
13696 if (decalsystem->model != model)
13697 R_DecalSystem_Reset(decalsystem);
13698 decalsystem->model = model;
13700 RSurf_ActiveModelEntity(ent, false, false, false);
13702 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13703 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13704 VectorNormalize(localnormal);
13705 localsize = worldsize*rsurface.inversematrixscale;
13706 localmins[0] = localorigin[0] - localsize;
13707 localmins[1] = localorigin[1] - localsize;
13708 localmins[2] = localorigin[2] - localsize;
13709 localmaxs[0] = localorigin[0] + localsize;
13710 localmaxs[1] = localorigin[1] + localsize;
13711 localmaxs[2] = localorigin[2] + localsize;
13713 //VectorCopy(localnormal, planes[4]);
13714 //VectorVectors(planes[4], planes[2], planes[0]);
13715 AnglesFromVectors(angles, localnormal, NULL, false);
13716 AngleVectors(angles, planes[0], planes[2], planes[4]);
13717 VectorNegate(planes[0], planes[1]);
13718 VectorNegate(planes[2], planes[3]);
13719 VectorNegate(planes[4], planes[5]);
13720 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13721 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13722 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13723 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13724 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13725 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13730 matrix4x4_t forwardprojection;
13731 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13732 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13737 float projectionvector[4][3];
13738 VectorScale(planes[0], ilocalsize, projectionvector[0]);
13739 VectorScale(planes[2], ilocalsize, projectionvector[1]);
13740 VectorScale(planes[4], ilocalsize, projectionvector[2]);
13741 projectionvector[0][0] = planes[0][0] * ilocalsize;
13742 projectionvector[0][1] = planes[1][0] * ilocalsize;
13743 projectionvector[0][2] = planes[2][0] * ilocalsize;
13744 projectionvector[1][0] = planes[0][1] * ilocalsize;
13745 projectionvector[1][1] = planes[1][1] * ilocalsize;
13746 projectionvector[1][2] = planes[2][1] * ilocalsize;
13747 projectionvector[2][0] = planes[0][2] * ilocalsize;
13748 projectionvector[2][1] = planes[1][2] * ilocalsize;
13749 projectionvector[2][2] = planes[2][2] * ilocalsize;
13750 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13751 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13752 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13753 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13757 dynamic = model->surfmesh.isanimated;
13758 numsurfacelist = model->nummodelsurfaces;
13759 surfacelist = model->sortedmodelsurfaces;
13760 surfaces = model->data_surfaces;
13763 bih_triangles_count = -1;
13766 if(model->render_bih.numleafs)
13767 bih = &model->render_bih;
13768 else if(model->collision_bih.numleafs)
13769 bih = &model->collision_bih;
13772 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13773 if(bih_triangles_count == 0)
13775 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13777 if(bih_triangles_count > 0)
13779 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13781 surfaceindex = bih_surfaces[triangleindex];
13782 surface = surfaces + surfaceindex;
13783 texture = surface->texture;
13784 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13786 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13788 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13793 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13795 surfaceindex = surfacelist[surfacelistindex];
13796 surface = surfaces + surfaceindex;
13797 // check cull box first because it rejects more than any other check
13798 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13800 // skip transparent surfaces
13801 texture = surface->texture;
13802 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13804 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13806 numtriangles = surface->num_triangles;
13807 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13808 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13813 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13814 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)
13816 int renderentityindex;
13817 float worldmins[3];
13818 float worldmaxs[3];
13819 entity_render_t *ent;
13821 if (!cl_decals_newsystem.integer)
13824 worldmins[0] = worldorigin[0] - worldsize;
13825 worldmins[1] = worldorigin[1] - worldsize;
13826 worldmins[2] = worldorigin[2] - worldsize;
13827 worldmaxs[0] = worldorigin[0] + worldsize;
13828 worldmaxs[1] = worldorigin[1] + worldsize;
13829 worldmaxs[2] = worldorigin[2] + worldsize;
13831 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13833 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13835 ent = r_refdef.scene.entities[renderentityindex];
13836 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13839 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13843 typedef struct r_decalsystem_splatqueue_s
13845 vec3_t worldorigin;
13846 vec3_t worldnormal;
13852 r_decalsystem_splatqueue_t;
13854 int r_decalsystem_numqueued = 0;
13855 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13857 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)
13859 r_decalsystem_splatqueue_t *queue;
13861 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13864 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13865 VectorCopy(worldorigin, queue->worldorigin);
13866 VectorCopy(worldnormal, queue->worldnormal);
13867 Vector4Set(queue->color, r, g, b, a);
13868 Vector4Set(queue->tcrange, s1, t1, s2, t2);
13869 queue->worldsize = worldsize;
13870 queue->decalsequence = cl.decalsequence++;
13873 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13876 r_decalsystem_splatqueue_t *queue;
13878 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13879 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);
13880 r_decalsystem_numqueued = 0;
13883 extern cvar_t cl_decals_max;
13884 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13887 decalsystem_t *decalsystem = &ent->decalsystem;
13894 if (!decalsystem->numdecals)
13897 if (r_showsurfaces.integer)
13900 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13902 R_DecalSystem_Reset(decalsystem);
13906 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13907 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13909 if (decalsystem->lastupdatetime)
13910 frametime = (cl.time - decalsystem->lastupdatetime);
13913 decalsystem->lastupdatetime = cl.time;
13914 decal = decalsystem->decals;
13915 numdecals = decalsystem->numdecals;
13917 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13919 if (decal->color4ub[0][3])
13921 decal->lived += frametime;
13922 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13924 memset(decal, 0, sizeof(*decal));
13925 if (decalsystem->freedecal > i)
13926 decalsystem->freedecal = i;
13930 decal = decalsystem->decals;
13931 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13934 // collapse the array by shuffling the tail decals into the gaps
13937 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13938 decalsystem->freedecal++;
13939 if (decalsystem->freedecal == numdecals)
13941 decal[decalsystem->freedecal] = decal[--numdecals];
13944 decalsystem->numdecals = numdecals;
13946 if (numdecals <= 0)
13948 // if there are no decals left, reset decalsystem
13949 R_DecalSystem_Reset(decalsystem);
13953 extern skinframe_t *decalskinframe;
13954 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13957 decalsystem_t *decalsystem = &ent->decalsystem;
13966 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13969 numdecals = decalsystem->numdecals;
13973 if (r_showsurfaces.integer)
13976 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13978 R_DecalSystem_Reset(decalsystem);
13982 // if the model is static it doesn't matter what value we give for
13983 // wantnormals and wanttangents, so this logic uses only rules applicable
13984 // to a model, knowing that they are meaningless otherwise
13985 if (ent == r_refdef.scene.worldentity)
13986 RSurf_ActiveWorldEntity();
13988 RSurf_ActiveModelEntity(ent, false, false, false);
13990 decalsystem->lastupdatetime = cl.time;
13991 decal = decalsystem->decals;
13993 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13995 // update vertex positions for animated models
13996 v3f = decalsystem->vertex3f;
13997 c4f = decalsystem->color4f;
13998 t2f = decalsystem->texcoord2f;
13999 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
14001 if (!decal->color4ub[0][3])
14004 if (surfacevisible && !surfacevisible[decal->surfaceindex])
14007 // update color values for fading decals
14008 if (decal->lived >= cl_decals_time.value)
14010 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
14011 alpha *= (1.0f/255.0f);
14014 alpha = 1.0f/255.0f;
14016 c4f[ 0] = decal->color4ub[0][0] * alpha;
14017 c4f[ 1] = decal->color4ub[0][1] * alpha;
14018 c4f[ 2] = decal->color4ub[0][2] * alpha;
14020 c4f[ 4] = decal->color4ub[1][0] * alpha;
14021 c4f[ 5] = decal->color4ub[1][1] * alpha;
14022 c4f[ 6] = decal->color4ub[1][2] * alpha;
14024 c4f[ 8] = decal->color4ub[2][0] * alpha;
14025 c4f[ 9] = decal->color4ub[2][1] * alpha;
14026 c4f[10] = decal->color4ub[2][2] * alpha;
14029 t2f[0] = decal->texcoord2f[0][0];
14030 t2f[1] = decal->texcoord2f[0][1];
14031 t2f[2] = decal->texcoord2f[1][0];
14032 t2f[3] = decal->texcoord2f[1][1];
14033 t2f[4] = decal->texcoord2f[2][0];
14034 t2f[5] = decal->texcoord2f[2][1];
14036 // update vertex positions for animated models
14037 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
14039 e = rsurface.modelelement3i + 3*decal->triangleindex;
14040 VectorCopy(rsurface.modelvertexposition[e[0]].vertex3f, v3f);
14041 VectorCopy(rsurface.modelvertexposition[e[1]].vertex3f, v3f + 3);
14042 VectorCopy(rsurface.modelvertexposition[e[2]].vertex3f, v3f + 6);
14046 VectorCopy(decal->vertex3f[0], v3f);
14047 VectorCopy(decal->vertex3f[1], v3f + 3);
14048 VectorCopy(decal->vertex3f[2], v3f + 6);
14051 if (r_refdef.fogenabled)
14053 alpha = RSurf_FogVertex(v3f);
14054 VectorScale(c4f, alpha, c4f);
14055 alpha = RSurf_FogVertex(v3f + 3);
14056 VectorScale(c4f + 4, alpha, c4f + 4);
14057 alpha = RSurf_FogVertex(v3f + 6);
14058 VectorScale(c4f + 8, alpha, c4f + 8);
14069 r_refdef.stats.drawndecals += numtris;
14071 // now render the decals all at once
14072 // (this assumes they all use one particle font texture!)
14073 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);
14074 // R_Mesh_ResetTextureState();
14075 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
14076 GL_DepthMask(false);
14077 GL_DepthRange(0, 1);
14078 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
14079 GL_DepthTest(true);
14080 GL_CullFace(GL_NONE);
14081 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
14082 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
14083 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
14087 static void R_DrawModelDecals(void)
14091 // fade faster when there are too many decals
14092 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14093 for (i = 0;i < r_refdef.scene.numentities;i++)
14094 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14096 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
14097 for (i = 0;i < r_refdef.scene.numentities;i++)
14098 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14099 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
14101 R_DecalSystem_ApplySplatEntitiesQueue();
14103 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14104 for (i = 0;i < r_refdef.scene.numentities;i++)
14105 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14107 r_refdef.stats.totaldecals += numdecals;
14109 if (r_showsurfaces.integer)
14112 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
14114 for (i = 0;i < r_refdef.scene.numentities;i++)
14116 if (!r_refdef.viewcache.entityvisible[i])
14118 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14119 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
14123 extern cvar_t mod_collision_bih;
14124 void R_DrawDebugModel(void)
14126 entity_render_t *ent = rsurface.entity;
14127 int i, j, k, l, flagsmask;
14128 const msurface_t *surface;
14129 dp_model_t *model = ent->model;
14132 switch(vid.renderpath)
14134 case RENDERPATH_GL11:
14135 case RENDERPATH_GL13:
14136 case RENDERPATH_GL20:
14137 case RENDERPATH_CGGL:
14139 case RENDERPATH_D3D9:
14140 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14142 case RENDERPATH_D3D10:
14143 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14145 case RENDERPATH_D3D11:
14146 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14150 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
14152 // R_Mesh_ResetTextureState();
14153 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
14154 GL_DepthRange(0, 1);
14155 GL_DepthTest(!r_showdisabledepthtest.integer);
14156 GL_DepthMask(false);
14157 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14159 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
14163 qboolean cullbox = ent == r_refdef.scene.worldentity;
14164 const q3mbrush_t *brush;
14165 const bih_t *bih = &model->collision_bih;
14166 const bih_leaf_t *bihleaf;
14167 float vertex3f[3][3];
14168 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
14170 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
14172 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
14174 switch (bihleaf->type)
14177 brush = model->brush.data_brushes + bihleaf->itemindex;
14178 if (brush->colbrushf && brush->colbrushf->numtriangles)
14180 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);
14181 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
14182 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
14185 case BIH_COLLISIONTRIANGLE:
14186 triangleindex = bihleaf->itemindex;
14187 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
14188 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
14189 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
14190 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);
14191 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14192 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14194 case BIH_RENDERTRIANGLE:
14195 triangleindex = bihleaf->itemindex;
14196 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
14197 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
14198 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
14199 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);
14200 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14201 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14207 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
14209 if (r_showtris.integer || r_shownormals.integer)
14211 if (r_showdisabledepthtest.integer)
14213 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14214 GL_DepthMask(false);
14218 GL_BlendFunc(GL_ONE, GL_ZERO);
14219 GL_DepthMask(true);
14221 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
14223 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
14225 rsurface.texture = R_GetCurrentTexture(surface->texture);
14226 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
14228 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
14229 if (r_showtris.value > 0)
14231 if (!rsurface.texture->currentlayers->depthmask)
14232 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
14233 else if (ent == r_refdef.scene.worldentity)
14234 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
14236 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
14237 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
14238 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
14240 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
14243 if (r_shownormals.value < 0)
14245 qglBegin(GL_LINES);
14246 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14248 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14249 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14250 qglVertex3f(v[0], v[1], v[2]);
14251 VectorMA(v, -r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14252 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14253 qglVertex3f(v[0], v[1], v[2]);
14258 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
14260 qglBegin(GL_LINES);
14261 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14263 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14264 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14265 qglVertex3f(v[0], v[1], v[2]);
14266 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14267 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14268 qglVertex3f(v[0], v[1], v[2]);
14272 qglBegin(GL_LINES);
14273 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14275 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14276 GL_Color(0, r_refdef.view.colorscale, 0, 1);
14277 qglVertex3f(v[0], v[1], v[2]);
14278 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
14279 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14280 qglVertex3f(v[0], v[1], v[2]);
14284 qglBegin(GL_LINES);
14285 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14287 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14288 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14289 qglVertex3f(v[0], v[1], v[2]);
14290 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14291 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14292 qglVertex3f(v[0], v[1], v[2]);
14299 rsurface.texture = NULL;
14303 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
14304 int r_maxsurfacelist = 0;
14305 const msurface_t **r_surfacelist = NULL;
14306 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14308 int i, j, endj, flagsmask;
14309 dp_model_t *model = r_refdef.scene.worldmodel;
14310 msurface_t *surfaces;
14311 unsigned char *update;
14312 int numsurfacelist = 0;
14316 if (r_maxsurfacelist < model->num_surfaces)
14318 r_maxsurfacelist = model->num_surfaces;
14320 Mem_Free((msurface_t**)r_surfacelist);
14321 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14324 RSurf_ActiveWorldEntity();
14326 surfaces = model->data_surfaces;
14327 update = model->brushq1.lightmapupdateflags;
14329 // update light styles on this submodel
14330 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14332 model_brush_lightstyleinfo_t *style;
14333 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14335 if (style->value != r_refdef.scene.lightstylevalue[style->style])
14337 int *list = style->surfacelist;
14338 style->value = r_refdef.scene.lightstylevalue[style->style];
14339 for (j = 0;j < style->numsurfaces;j++)
14340 update[list[j]] = true;
14345 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14349 R_DrawDebugModel();
14350 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14354 rsurface.lightmaptexture = NULL;
14355 rsurface.deluxemaptexture = NULL;
14356 rsurface.uselightmaptexture = false;
14357 rsurface.texture = NULL;
14358 rsurface.rtlight = NULL;
14359 numsurfacelist = 0;
14360 // add visible surfaces to draw list
14361 for (i = 0;i < model->nummodelsurfaces;i++)
14363 j = model->sortedmodelsurfaces[i];
14364 if (r_refdef.viewcache.world_surfacevisible[j])
14365 r_surfacelist[numsurfacelist++] = surfaces + j;
14367 // update lightmaps if needed
14368 if (model->brushq1.firstrender)
14370 model->brushq1.firstrender = false;
14371 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14373 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14377 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14378 if (r_refdef.viewcache.world_surfacevisible[j])
14380 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14382 // don't do anything if there were no surfaces
14383 if (!numsurfacelist)
14385 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14388 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14389 GL_AlphaTest(false);
14391 // add to stats if desired
14392 if (r_speeds.integer && !skysurfaces && !depthonly)
14394 r_refdef.stats.world_surfaces += numsurfacelist;
14395 for (j = 0;j < numsurfacelist;j++)
14396 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
14399 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14402 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14404 int i, j, endj, flagsmask;
14405 dp_model_t *model = ent->model;
14406 msurface_t *surfaces;
14407 unsigned char *update;
14408 int numsurfacelist = 0;
14412 if (r_maxsurfacelist < model->num_surfaces)
14414 r_maxsurfacelist = model->num_surfaces;
14416 Mem_Free((msurface_t **)r_surfacelist);
14417 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14420 // if the model is static it doesn't matter what value we give for
14421 // wantnormals and wanttangents, so this logic uses only rules applicable
14422 // to a model, knowing that they are meaningless otherwise
14423 if (ent == r_refdef.scene.worldentity)
14424 RSurf_ActiveWorldEntity();
14425 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14426 RSurf_ActiveModelEntity(ent, false, false, false);
14428 RSurf_ActiveModelEntity(ent, true, true, true);
14429 else if (depthonly)
14431 switch (vid.renderpath)
14433 case RENDERPATH_GL20:
14434 case RENDERPATH_CGGL:
14435 case RENDERPATH_D3D9:
14436 case RENDERPATH_D3D10:
14437 case RENDERPATH_D3D11:
14438 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14440 case RENDERPATH_GL13:
14441 case RENDERPATH_GL11:
14442 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14448 switch (vid.renderpath)
14450 case RENDERPATH_GL20:
14451 case RENDERPATH_CGGL:
14452 case RENDERPATH_D3D9:
14453 case RENDERPATH_D3D10:
14454 case RENDERPATH_D3D11:
14455 RSurf_ActiveModelEntity(ent, true, true, false);
14457 case RENDERPATH_GL13:
14458 case RENDERPATH_GL11:
14459 RSurf_ActiveModelEntity(ent, true, false, false);
14464 surfaces = model->data_surfaces;
14465 update = model->brushq1.lightmapupdateflags;
14467 // update light styles
14468 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14470 model_brush_lightstyleinfo_t *style;
14471 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14473 if (style->value != r_refdef.scene.lightstylevalue[style->style])
14475 int *list = style->surfacelist;
14476 style->value = r_refdef.scene.lightstylevalue[style->style];
14477 for (j = 0;j < style->numsurfaces;j++)
14478 update[list[j]] = true;
14483 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14487 R_DrawDebugModel();
14488 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14492 rsurface.lightmaptexture = NULL;
14493 rsurface.deluxemaptexture = NULL;
14494 rsurface.uselightmaptexture = false;
14495 rsurface.texture = NULL;
14496 rsurface.rtlight = NULL;
14497 numsurfacelist = 0;
14498 // add visible surfaces to draw list
14499 for (i = 0;i < model->nummodelsurfaces;i++)
14500 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14501 // don't do anything if there were no surfaces
14502 if (!numsurfacelist)
14504 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14507 // update lightmaps if needed
14511 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14516 R_BuildLightMap(ent, surfaces + j);
14521 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14523 R_BuildLightMap(ent, surfaces + j);
14524 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14525 GL_AlphaTest(false);
14527 // add to stats if desired
14528 if (r_speeds.integer && !skysurfaces && !depthonly)
14530 r_refdef.stats.entities_surfaces += numsurfacelist;
14531 for (j = 0;j < numsurfacelist;j++)
14532 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14535 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14538 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14540 static texture_t texture;
14541 static msurface_t surface;
14542 const msurface_t *surfacelist = &surface;
14544 // fake enough texture and surface state to render this geometry
14546 texture.update_lastrenderframe = -1; // regenerate this texture
14547 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14548 texture.currentskinframe = skinframe;
14549 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14550 texture.offsetmapping = OFFSETMAPPING_OFF;
14551 texture.offsetscale = 1;
14552 texture.specularscalemod = 1;
14553 texture.specularpowermod = 1;
14555 surface.texture = &texture;
14556 surface.num_triangles = numtriangles;
14557 surface.num_firsttriangle = firsttriangle;
14558 surface.num_vertices = numvertices;
14559 surface.num_firstvertex = firstvertex;
14562 rsurface.texture = R_GetCurrentTexture(surface.texture);
14563 rsurface.lightmaptexture = NULL;
14564 rsurface.deluxemaptexture = NULL;
14565 rsurface.uselightmaptexture = false;
14566 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14569 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)
14571 static msurface_t surface;
14572 const msurface_t *surfacelist = &surface;
14574 // fake enough texture and surface state to render this geometry
14575 surface.texture = texture;
14576 surface.num_triangles = numtriangles;
14577 surface.num_firsttriangle = firsttriangle;
14578 surface.num_vertices = numvertices;
14579 surface.num_firstvertex = firstvertex;
14582 rsurface.texture = R_GetCurrentTexture(surface.texture);
14583 rsurface.lightmaptexture = NULL;
14584 rsurface.deluxemaptexture = NULL;
14585 rsurface.uselightmaptexture = false;
14586 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);