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 + float2(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);\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 is multiplied by SHADERPERMUTATION_MODEBASE
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, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
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"},
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_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3477 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3478 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3479 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3480 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3481 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3482 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3483 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3484 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3488 struct r_glsl_permutation_s;
3489 typedef struct r_glsl_permutation_s
3491 /// hash lookup data
3492 struct r_glsl_permutation_s *hashnext;
3494 unsigned int permutation;
3496 /// indicates if we have tried compiling this permutation already
3498 /// 0 if compilation failed
3500 /// locations of detected uniforms in program object, or -1 if not found
3501 int loc_Texture_First;
3502 int loc_Texture_Second;
3503 int loc_Texture_GammaRamps;
3504 int loc_Texture_Normal;
3505 int loc_Texture_Color;
3506 int loc_Texture_Gloss;
3507 int loc_Texture_Glow;
3508 int loc_Texture_SecondaryNormal;
3509 int loc_Texture_SecondaryColor;
3510 int loc_Texture_SecondaryGloss;
3511 int loc_Texture_SecondaryGlow;
3512 int loc_Texture_Pants;
3513 int loc_Texture_Shirt;
3514 int loc_Texture_FogHeightTexture;
3515 int loc_Texture_FogMask;
3516 int loc_Texture_Lightmap;
3517 int loc_Texture_Deluxemap;
3518 int loc_Texture_Attenuation;
3519 int loc_Texture_Cube;
3520 int loc_Texture_Refraction;
3521 int loc_Texture_Reflection;
3522 int loc_Texture_ShadowMap2D;
3523 int loc_Texture_CubeProjection;
3524 int loc_Texture_ScreenDepth;
3525 int loc_Texture_ScreenNormalMap;
3526 int loc_Texture_ScreenDiffuse;
3527 int loc_Texture_ScreenSpecular;
3528 int loc_Texture_ReflectMask;
3529 int loc_Texture_ReflectCube;
3531 int loc_BloomBlur_Parameters;
3533 int loc_Color_Ambient;
3534 int loc_Color_Diffuse;
3535 int loc_Color_Specular;
3537 int loc_Color_Pants;
3538 int loc_Color_Shirt;
3539 int loc_DeferredColor_Ambient;
3540 int loc_DeferredColor_Diffuse;
3541 int loc_DeferredColor_Specular;
3542 int loc_DeferredMod_Diffuse;
3543 int loc_DeferredMod_Specular;
3544 int loc_DistortScaleRefractReflect;
3545 int loc_EyePosition;
3547 int loc_FogHeightFade;
3549 int loc_FogPlaneViewDist;
3550 int loc_FogRangeRecip;
3553 int loc_LightPosition;
3554 int loc_OffsetMapping_Scale;
3556 int loc_ReflectColor;
3557 int loc_ReflectFactor;
3558 int loc_ReflectOffset;
3559 int loc_RefractColor;
3561 int loc_ScreenCenterRefractReflect;
3562 int loc_ScreenScaleRefractReflect;
3563 int loc_ScreenToDepth;
3564 int loc_ShadowMap_Parameters;
3565 int loc_ShadowMap_TextureScale;
3566 int loc_SpecularPower;
3571 int loc_ViewTintColor;
3572 int loc_ViewToLight;
3573 int loc_ModelToLight;
3575 int loc_BackgroundTexMatrix;
3576 int loc_ModelViewProjectionMatrix;
3577 int loc_ModelViewMatrix;
3578 int loc_PixelToScreenTexCoord;
3579 int loc_ModelToReflectCube;
3580 int loc_ShadowMapMatrix;
3581 int loc_BloomColorSubtract;
3582 int loc_NormalmapScrollBlend;
3584 r_glsl_permutation_t;
3586 #define SHADERPERMUTATION_HASHSIZE 256
3589 // non-degradable "lightweight" shader parameters to keep the permutations simpler
3590 // these can NOT degrade! only use for simple stuff
3593 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
3594 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3595 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
3596 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
3597 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
3598 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5 ///< postprocess uservec4 is enabled
3600 #define SHADERSTATICPARMS_COUNT 6
3602 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
3603 static int shaderstaticparms_count = 0;
3605 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
3606 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
3607 qboolean R_CompileShader_CheckStaticParms(void)
3609 static int r_compileshader_staticparms_save[1];
3610 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
3611 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
3614 if (r_glsl_saturation_redcompensate.integer)
3615 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
3616 if (r_shadow_glossexact.integer)
3617 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
3618 if (r_glsl_postprocess.integer)
3620 if (r_glsl_postprocess_uservec1_enable.integer)
3621 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
3622 if (r_glsl_postprocess_uservec2_enable.integer)
3623 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
3624 if (r_glsl_postprocess_uservec3_enable.integer)
3625 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
3626 if (r_glsl_postprocess_uservec4_enable.integer)
3627 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
3629 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
3632 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
3633 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
3634 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
3636 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
3637 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
3639 shaderstaticparms_count = 0;
3642 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
3643 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
3644 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
3645 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
3646 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
3647 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
3650 /// information about each possible shader permutation
3651 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3652 /// currently selected permutation
3653 r_glsl_permutation_t *r_glsl_permutation;
3654 /// storage for permutations linked in the hash table
3655 memexpandablearray_t r_glsl_permutationarray;
3657 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3659 //unsigned int hashdepth = 0;
3660 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3661 r_glsl_permutation_t *p;
3662 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3664 if (p->mode == mode && p->permutation == permutation)
3666 //if (hashdepth > 10)
3667 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3672 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3674 p->permutation = permutation;
3675 p->hashnext = r_glsl_permutationhash[mode][hashindex];
3676 r_glsl_permutationhash[mode][hashindex] = p;
3677 //if (hashdepth > 10)
3678 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3682 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3685 if (!filename || !filename[0])
3687 if (!strcmp(filename, "glsl/default.glsl"))
3689 if (!glslshaderstring)
3691 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3692 if (glslshaderstring)
3693 Con_DPrintf("Loading shaders from file %s...\n", filename);
3695 glslshaderstring = (char *)builtinshaderstring;
3697 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3698 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3699 return shaderstring;
3701 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3704 if (printfromdisknotice)
3705 Con_DPrintf("from disk %s... ", filename);
3706 return shaderstring;
3708 return shaderstring;
3711 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3714 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3715 char *vertexstring, *geometrystring, *fragmentstring;
3716 char permutationname[256];
3717 int vertstrings_count = 0;
3718 int geomstrings_count = 0;
3719 int fragstrings_count = 0;
3720 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3721 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3722 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3729 permutationname[0] = 0;
3730 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
3731 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3732 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3734 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3736 // the first pretext is which type of shader to compile as
3737 // (later these will all be bound together as a program object)
3738 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3739 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3740 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3742 // the second pretext is the mode (for example a light source)
3743 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3744 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3745 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3746 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3748 // now add all the permutation pretexts
3749 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3751 if (permutation & (1<<i))
3753 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3754 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3755 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3756 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3760 // keep line numbers correct
3761 vertstrings_list[vertstrings_count++] = "\n";
3762 geomstrings_list[geomstrings_count++] = "\n";
3763 fragstrings_list[fragstrings_count++] = "\n";
3768 R_CompileShader_AddStaticParms(mode, permutation);
3769 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3770 vertstrings_count += shaderstaticparms_count;
3771 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3772 geomstrings_count += shaderstaticparms_count;
3773 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3774 fragstrings_count += shaderstaticparms_count;
3776 // now append the shader text itself
3777 vertstrings_list[vertstrings_count++] = vertexstring;
3778 geomstrings_list[geomstrings_count++] = geometrystring;
3779 fragstrings_list[fragstrings_count++] = fragmentstring;
3781 // if any sources were NULL, clear the respective list
3783 vertstrings_count = 0;
3784 if (!geometrystring)
3785 geomstrings_count = 0;
3786 if (!fragmentstring)
3787 fragstrings_count = 0;
3789 // compile the shader program
3790 if (vertstrings_count + geomstrings_count + fragstrings_count)
3791 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3795 qglUseProgramObjectARB(p->program);CHECKGLERROR
3796 // look up all the uniform variable names we care about, so we don't
3797 // have to look them up every time we set them
3799 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
3800 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
3801 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3802 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
3803 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
3804 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3805 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
3806 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3807 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3808 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3809 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3810 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
3811 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3812 p->loc_Texture_FogHeightTexture = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3813 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3814 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3815 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3816 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3817 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
3818 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3819 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3820 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3821 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3822 p->loc_Texture_ScreenDepth = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3823 p->loc_Texture_ScreenNormalMap = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3824 p->loc_Texture_ScreenDiffuse = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3825 p->loc_Texture_ScreenSpecular = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3826 p->loc_Texture_ReflectMask = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3827 p->loc_Texture_ReflectCube = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3828 p->loc_Alpha = qglGetUniformLocationARB(p->program, "Alpha");
3829 p->loc_BloomBlur_Parameters = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3830 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
3831 p->loc_Color_Ambient = qglGetUniformLocationARB(p->program, "Color_Ambient");
3832 p->loc_Color_Diffuse = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3833 p->loc_Color_Specular = qglGetUniformLocationARB(p->program, "Color_Specular");
3834 p->loc_Color_Glow = qglGetUniformLocationARB(p->program, "Color_Glow");
3835 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
3836 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
3837 p->loc_DeferredColor_Ambient = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3838 p->loc_DeferredColor_Diffuse = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3839 p->loc_DeferredColor_Specular = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3840 p->loc_DeferredMod_Diffuse = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3841 p->loc_DeferredMod_Specular = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3842 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3843 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
3844 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
3845 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
3846 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
3847 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3848 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3849 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
3850 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
3851 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
3852 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3853 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
3854 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
3855 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
3856 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
3857 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
3858 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
3859 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3860 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3861 p->loc_ScreenToDepth = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3862 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3863 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3864 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
3865 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
3866 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
3867 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
3868 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
3869 p->loc_ViewTintColor = qglGetUniformLocationARB(p->program, "ViewTintColor");
3870 p->loc_ViewToLight = qglGetUniformLocationARB(p->program, "ViewToLight");
3871 p->loc_ModelToLight = qglGetUniformLocationARB(p->program, "ModelToLight");
3872 p->loc_TexMatrix = qglGetUniformLocationARB(p->program, "TexMatrix");
3873 p->loc_BackgroundTexMatrix = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3874 p->loc_ModelViewMatrix = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3875 p->loc_ModelViewProjectionMatrix = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3876 p->loc_PixelToScreenTexCoord = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3877 p->loc_ModelToReflectCube = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3878 p->loc_ShadowMapMatrix = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3879 p->loc_BloomColorSubtract = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
3880 p->loc_NormalmapScrollBlend = qglGetUniformLocationARB(p->program, "NormalmapScrollBlend");
3881 // initialize the samplers to refer to the texture units we use
3882 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
3883 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
3884 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
3885 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
3886 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
3887 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
3888 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
3889 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3890 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3891 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3892 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
3893 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
3894 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
3895 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3896 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
3897 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
3898 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
3899 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
3900 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
3901 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
3902 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
3903 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
3904 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3905 if (p->loc_Texture_ScreenDepth >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth , GL20TU_SCREENDEPTH);
3906 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3907 if (p->loc_Texture_ScreenDiffuse >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse , GL20TU_SCREENDIFFUSE);
3908 if (p->loc_Texture_ScreenSpecular >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3909 if (p->loc_Texture_ReflectMask >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask , GL20TU_REFLECTMASK);
3910 if (p->loc_Texture_ReflectCube >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube , GL20TU_REFLECTCUBE);
3912 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3915 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
3919 Mem_Free(vertexstring);
3921 Mem_Free(geometrystring);
3923 Mem_Free(fragmentstring);
3926 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3928 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3929 if (r_glsl_permutation != perm)
3931 r_glsl_permutation = perm;
3932 if (!r_glsl_permutation->program)
3934 if (!r_glsl_permutation->compiled)
3935 R_GLSL_CompilePermutation(perm, mode, permutation);
3936 if (!r_glsl_permutation->program)
3938 // remove features until we find a valid permutation
3940 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3942 // reduce i more quickly whenever it would not remove any bits
3943 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3944 if (!(permutation & j))
3947 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3948 if (!r_glsl_permutation->compiled)
3949 R_GLSL_CompilePermutation(perm, mode, permutation);
3950 if (r_glsl_permutation->program)
3953 if (i >= SHADERPERMUTATION_COUNT)
3955 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3956 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3957 qglUseProgramObjectARB(0);CHECKGLERROR
3958 return; // no bit left to clear, entire mode is broken
3963 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3965 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3966 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3967 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3971 #include <Cg/cgGL.h>
3972 struct r_cg_permutation_s;
3973 typedef struct r_cg_permutation_s
3975 /// hash lookup data
3976 struct r_cg_permutation_s *hashnext;
3978 unsigned int permutation;
3980 /// indicates if we have tried compiling this permutation already
3982 /// 0 if compilation failed
3985 /// locations of detected parameters in programs, or NULL if not found
3986 CGparameter vp_EyePosition;
3987 CGparameter vp_FogPlane;
3988 CGparameter vp_LightDir;
3989 CGparameter vp_LightPosition;
3990 CGparameter vp_ModelToLight;
3991 CGparameter vp_TexMatrix;
3992 CGparameter vp_BackgroundTexMatrix;
3993 CGparameter vp_ModelViewProjectionMatrix;
3994 CGparameter vp_ModelViewMatrix;
3995 CGparameter vp_ShadowMapMatrix;
3997 CGparameter fp_Texture_First;
3998 CGparameter fp_Texture_Second;
3999 CGparameter fp_Texture_GammaRamps;
4000 CGparameter fp_Texture_Normal;
4001 CGparameter fp_Texture_Color;
4002 CGparameter fp_Texture_Gloss;
4003 CGparameter fp_Texture_Glow;
4004 CGparameter fp_Texture_SecondaryNormal;
4005 CGparameter fp_Texture_SecondaryColor;
4006 CGparameter fp_Texture_SecondaryGloss;
4007 CGparameter fp_Texture_SecondaryGlow;
4008 CGparameter fp_Texture_Pants;
4009 CGparameter fp_Texture_Shirt;
4010 CGparameter fp_Texture_FogHeightTexture;
4011 CGparameter fp_Texture_FogMask;
4012 CGparameter fp_Texture_Lightmap;
4013 CGparameter fp_Texture_Deluxemap;
4014 CGparameter fp_Texture_Attenuation;
4015 CGparameter fp_Texture_Cube;
4016 CGparameter fp_Texture_Refraction;
4017 CGparameter fp_Texture_Reflection;
4018 CGparameter fp_Texture_ShadowMap2D;
4019 CGparameter fp_Texture_CubeProjection;
4020 CGparameter fp_Texture_ScreenDepth;
4021 CGparameter fp_Texture_ScreenNormalMap;
4022 CGparameter fp_Texture_ScreenDiffuse;
4023 CGparameter fp_Texture_ScreenSpecular;
4024 CGparameter fp_Texture_ReflectMask;
4025 CGparameter fp_Texture_ReflectCube;
4026 CGparameter fp_Alpha;
4027 CGparameter fp_BloomBlur_Parameters;
4028 CGparameter fp_ClientTime;
4029 CGparameter fp_Color_Ambient;
4030 CGparameter fp_Color_Diffuse;
4031 CGparameter fp_Color_Specular;
4032 CGparameter fp_Color_Glow;
4033 CGparameter fp_Color_Pants;
4034 CGparameter fp_Color_Shirt;
4035 CGparameter fp_DeferredColor_Ambient;
4036 CGparameter fp_DeferredColor_Diffuse;
4037 CGparameter fp_DeferredColor_Specular;
4038 CGparameter fp_DeferredMod_Diffuse;
4039 CGparameter fp_DeferredMod_Specular;
4040 CGparameter fp_DistortScaleRefractReflect;
4041 CGparameter fp_EyePosition;
4042 CGparameter fp_FogColor;
4043 CGparameter fp_FogHeightFade;
4044 CGparameter fp_FogPlane;
4045 CGparameter fp_FogPlaneViewDist;
4046 CGparameter fp_FogRangeRecip;
4047 CGparameter fp_LightColor;
4048 CGparameter fp_LightDir;
4049 CGparameter fp_LightPosition;
4050 CGparameter fp_OffsetMapping_Scale;
4051 CGparameter fp_PixelSize;
4052 CGparameter fp_ReflectColor;
4053 CGparameter fp_ReflectFactor;
4054 CGparameter fp_ReflectOffset;
4055 CGparameter fp_RefractColor;
4056 CGparameter fp_Saturation;
4057 CGparameter fp_ScreenCenterRefractReflect;
4058 CGparameter fp_ScreenScaleRefractReflect;
4059 CGparameter fp_ScreenToDepth;
4060 CGparameter fp_ShadowMap_Parameters;
4061 CGparameter fp_ShadowMap_TextureScale;
4062 CGparameter fp_SpecularPower;
4063 CGparameter fp_UserVec1;
4064 CGparameter fp_UserVec2;
4065 CGparameter fp_UserVec3;
4066 CGparameter fp_UserVec4;
4067 CGparameter fp_ViewTintColor;
4068 CGparameter fp_ViewToLight;
4069 CGparameter fp_PixelToScreenTexCoord;
4070 CGparameter fp_ModelToReflectCube;
4071 CGparameter fp_BloomColorSubtract;
4072 CGparameter fp_NormalmapScrollBlend;
4076 /// information about each possible shader permutation
4077 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4078 /// currently selected permutation
4079 r_cg_permutation_t *r_cg_permutation;
4080 /// storage for permutations linked in the hash table
4081 memexpandablearray_t r_cg_permutationarray;
4083 #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));}}
4085 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
4087 //unsigned int hashdepth = 0;
4088 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4089 r_cg_permutation_t *p;
4090 for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4092 if (p->mode == mode && p->permutation == permutation)
4094 //if (hashdepth > 10)
4095 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4100 p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4102 p->permutation = permutation;
4103 p->hashnext = r_cg_permutationhash[mode][hashindex];
4104 r_cg_permutationhash[mode][hashindex] = p;
4105 //if (hashdepth > 10)
4106 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4110 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4113 if (!filename || !filename[0])
4115 if (!strcmp(filename, "cg/default.cg"))
4117 if (!cgshaderstring)
4119 cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4121 Con_DPrintf("Loading shaders from file %s...\n", filename);
4123 cgshaderstring = (char *)builtincgshaderstring;
4125 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4126 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4127 return shaderstring;
4129 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4132 if (printfromdisknotice)
4133 Con_DPrintf("from disk %s... ", filename);
4134 return shaderstring;
4136 return shaderstring;
4139 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4141 // TODO: load or create .fp and .vp shader files
4144 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4147 shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4148 int vertstring_length = 0;
4149 int geomstring_length = 0;
4150 int fragstring_length = 0;
4152 char *vertexstring, *geometrystring, *fragmentstring;
4153 char *vertstring, *geomstring, *fragstring;
4154 char permutationname[256];
4155 char cachename[256];
4156 CGprofile vertexProfile;
4157 CGprofile fragmentProfile;
4158 int vertstrings_count = 0;
4159 int geomstrings_count = 0;
4160 int fragstrings_count = 0;
4161 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4162 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4163 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4171 permutationname[0] = 0;
4173 vertexstring = R_CG_GetText(modeinfo->vertexfilename, true);
4174 geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4175 fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4177 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4178 strlcat(cachename, "cg/", sizeof(cachename));
4180 // the first pretext is which type of shader to compile as
4181 // (later these will all be bound together as a program object)
4182 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4183 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4184 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4186 // the second pretext is the mode (for example a light source)
4187 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4188 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4189 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4190 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4191 strlcat(cachename, modeinfo->name, sizeof(cachename));
4193 // now add all the permutation pretexts
4194 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4196 if (permutation & (1<<i))
4198 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4199 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4200 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4201 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4202 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4206 // keep line numbers correct
4207 vertstrings_list[vertstrings_count++] = "\n";
4208 geomstrings_list[geomstrings_count++] = "\n";
4209 fragstrings_list[fragstrings_count++] = "\n";
4214 R_CompileShader_AddStaticParms(mode, permutation);
4215 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4216 vertstrings_count += shaderstaticparms_count;
4217 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4218 geomstrings_count += shaderstaticparms_count;
4219 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4220 fragstrings_count += shaderstaticparms_count;
4222 // replace spaces in the cachename with _ characters
4223 for (i = 0;cachename[i];i++)
4224 if (cachename[i] == ' ')
4227 // now append the shader text itself
4228 vertstrings_list[vertstrings_count++] = vertexstring;
4229 geomstrings_list[geomstrings_count++] = geometrystring;
4230 fragstrings_list[fragstrings_count++] = fragmentstring;
4232 // if any sources were NULL, clear the respective list
4234 vertstrings_count = 0;
4235 if (!geometrystring)
4236 geomstrings_count = 0;
4237 if (!fragmentstring)
4238 fragstrings_count = 0;
4240 vertstring_length = 0;
4241 for (i = 0;i < vertstrings_count;i++)
4242 vertstring_length += strlen(vertstrings_list[i]);
4243 vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4244 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4245 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4247 geomstring_length = 0;
4248 for (i = 0;i < geomstrings_count;i++)
4249 geomstring_length += strlen(geomstrings_list[i]);
4250 geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4251 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4252 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4254 fragstring_length = 0;
4255 for (i = 0;i < fragstrings_count;i++)
4256 fragstring_length += strlen(fragstrings_list[i]);
4257 fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4258 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4259 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4263 //vertexProfile = CG_PROFILE_ARBVP1;
4264 //fragmentProfile = CG_PROFILE_ARBFP1;
4265 vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4266 fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4267 //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4268 //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4269 //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4272 // try to load the cached shader, or generate one
4273 R_CG_CacheShader(p, cachename, vertstring, fragstring);
4275 // if caching failed, do a dynamic compile for now
4277 if (vertstring[0] && !p->vprogram)
4278 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4280 if (fragstring[0] && !p->fprogram)
4281 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4284 // look up all the uniform variable names we care about, so we don't
4285 // have to look them up every time we set them
4289 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4290 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4291 p->vp_EyePosition = cgGetNamedParameter(p->vprogram, "EyePosition");
4292 p->vp_FogPlane = cgGetNamedParameter(p->vprogram, "FogPlane");
4293 p->vp_LightDir = cgGetNamedParameter(p->vprogram, "LightDir");
4294 p->vp_LightPosition = cgGetNamedParameter(p->vprogram, "LightPosition");
4295 p->vp_ModelToLight = cgGetNamedParameter(p->vprogram, "ModelToLight");
4296 p->vp_TexMatrix = cgGetNamedParameter(p->vprogram, "TexMatrix");
4297 p->vp_BackgroundTexMatrix = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4298 p->vp_ModelViewProjectionMatrix = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4299 p->vp_ModelViewMatrix = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4300 p->vp_ShadowMapMatrix = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4306 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4307 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4308 p->fp_Texture_First = cgGetNamedParameter(p->fprogram, "Texture_First");
4309 p->fp_Texture_Second = cgGetNamedParameter(p->fprogram, "Texture_Second");
4310 p->fp_Texture_GammaRamps = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4311 p->fp_Texture_Normal = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4312 p->fp_Texture_Color = cgGetNamedParameter(p->fprogram, "Texture_Color");
4313 p->fp_Texture_Gloss = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4314 p->fp_Texture_Glow = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4315 p->fp_Texture_SecondaryNormal = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4316 p->fp_Texture_SecondaryColor = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4317 p->fp_Texture_SecondaryGloss = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4318 p->fp_Texture_SecondaryGlow = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4319 p->fp_Texture_Pants = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4320 p->fp_Texture_Shirt = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4321 p->fp_Texture_FogHeightTexture = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4322 p->fp_Texture_FogMask = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4323 p->fp_Texture_Lightmap = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4324 p->fp_Texture_Deluxemap = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4325 p->fp_Texture_Attenuation = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4326 p->fp_Texture_Cube = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4327 p->fp_Texture_Refraction = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4328 p->fp_Texture_Reflection = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4329 p->fp_Texture_ShadowMap2D = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4330 p->fp_Texture_CubeProjection = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4331 p->fp_Texture_ScreenDepth = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4332 p->fp_Texture_ScreenNormalMap = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4333 p->fp_Texture_ScreenDiffuse = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4334 p->fp_Texture_ScreenSpecular = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4335 p->fp_Texture_ReflectMask = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4336 p->fp_Texture_ReflectCube = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4337 p->fp_Alpha = cgGetNamedParameter(p->fprogram, "Alpha");
4338 p->fp_BloomBlur_Parameters = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4339 p->fp_ClientTime = cgGetNamedParameter(p->fprogram, "ClientTime");
4340 p->fp_Color_Ambient = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4341 p->fp_Color_Diffuse = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4342 p->fp_Color_Specular = cgGetNamedParameter(p->fprogram, "Color_Specular");
4343 p->fp_Color_Glow = cgGetNamedParameter(p->fprogram, "Color_Glow");
4344 p->fp_Color_Pants = cgGetNamedParameter(p->fprogram, "Color_Pants");
4345 p->fp_Color_Shirt = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4346 p->fp_DeferredColor_Ambient = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4347 p->fp_DeferredColor_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4348 p->fp_DeferredColor_Specular = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4349 p->fp_DeferredMod_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4350 p->fp_DeferredMod_Specular = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4351 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4352 p->fp_EyePosition = cgGetNamedParameter(p->fprogram, "EyePosition");
4353 p->fp_FogColor = cgGetNamedParameter(p->fprogram, "FogColor");
4354 p->fp_FogHeightFade = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4355 p->fp_FogPlane = cgGetNamedParameter(p->fprogram, "FogPlane");
4356 p->fp_FogPlaneViewDist = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4357 p->fp_FogRangeRecip = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4358 p->fp_LightColor = cgGetNamedParameter(p->fprogram, "LightColor");
4359 p->fp_LightDir = cgGetNamedParameter(p->fprogram, "LightDir");
4360 p->fp_LightPosition = cgGetNamedParameter(p->fprogram, "LightPosition");
4361 p->fp_OffsetMapping_Scale = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4362 p->fp_PixelSize = cgGetNamedParameter(p->fprogram, "PixelSize");
4363 p->fp_ReflectColor = cgGetNamedParameter(p->fprogram, "ReflectColor");
4364 p->fp_ReflectFactor = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4365 p->fp_ReflectOffset = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4366 p->fp_RefractColor = cgGetNamedParameter(p->fprogram, "RefractColor");
4367 p->fp_Saturation = cgGetNamedParameter(p->fprogram, "Saturation");
4368 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4369 p->fp_ScreenScaleRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4370 p->fp_ScreenToDepth = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4371 p->fp_ShadowMap_Parameters = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4372 p->fp_ShadowMap_TextureScale = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4373 p->fp_SpecularPower = cgGetNamedParameter(p->fprogram, "SpecularPower");
4374 p->fp_UserVec1 = cgGetNamedParameter(p->fprogram, "UserVec1");
4375 p->fp_UserVec2 = cgGetNamedParameter(p->fprogram, "UserVec2");
4376 p->fp_UserVec3 = cgGetNamedParameter(p->fprogram, "UserVec3");
4377 p->fp_UserVec4 = cgGetNamedParameter(p->fprogram, "UserVec4");
4378 p->fp_ViewTintColor = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4379 p->fp_ViewToLight = cgGetNamedParameter(p->fprogram, "ViewToLight");
4380 p->fp_PixelToScreenTexCoord = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4381 p->fp_ModelToReflectCube = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4382 p->fp_BloomColorSubtract = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4383 p->fp_NormalmapScrollBlend = cgGetNamedParameter(p->fprogram, "NormalmapScrollBlend");
4387 if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4388 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4390 Con_Printf("^1CG shader %s failed! some features may not work properly.\n", permutationname);
4394 Mem_Free(vertstring);
4396 Mem_Free(geomstring);
4398 Mem_Free(fragstring);
4400 Mem_Free(vertexstring);
4402 Mem_Free(geometrystring);
4404 Mem_Free(fragmentstring);
4407 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4409 r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4412 if (r_cg_permutation != perm)
4414 r_cg_permutation = perm;
4415 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4417 if (!r_cg_permutation->compiled)
4418 R_CG_CompilePermutation(perm, mode, permutation);
4419 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4421 // remove features until we find a valid permutation
4423 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4425 // reduce i more quickly whenever it would not remove any bits
4426 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4427 if (!(permutation & j))
4430 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4431 if (!r_cg_permutation->compiled)
4432 R_CG_CompilePermutation(perm, mode, permutation);
4433 if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4436 if (i >= SHADERPERMUTATION_COUNT)
4438 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4439 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4440 return; // no bit left to clear, entire mode is broken
4446 if (r_cg_permutation->vprogram)
4448 cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4449 cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4450 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4454 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4455 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4457 if (r_cg_permutation->fprogram)
4459 cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4460 cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4461 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4465 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4466 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4470 if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4471 if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4472 if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4475 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4477 cgGLSetTextureParameter(param, R_GetTexture(tex));
4478 cgGLEnableTextureParameter(param);
4486 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4487 extern D3DCAPS9 vid_d3d9caps;
4490 struct r_hlsl_permutation_s;
4491 typedef struct r_hlsl_permutation_s
4493 /// hash lookup data
4494 struct r_hlsl_permutation_s *hashnext;
4496 unsigned int permutation;
4498 /// indicates if we have tried compiling this permutation already
4500 /// NULL if compilation failed
4501 IDirect3DVertexShader9 *vertexshader;
4502 IDirect3DPixelShader9 *pixelshader;
4504 r_hlsl_permutation_t;
4506 typedef enum D3DVSREGISTER_e
4508 D3DVSREGISTER_TexMatrix = 0, // float4x4
4509 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4510 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4511 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4512 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4513 D3DVSREGISTER_ModelToLight = 20, // float4x4
4514 D3DVSREGISTER_EyePosition = 24,
4515 D3DVSREGISTER_FogPlane = 25,
4516 D3DVSREGISTER_LightDir = 26,
4517 D3DVSREGISTER_LightPosition = 27,
4521 typedef enum D3DPSREGISTER_e
4523 D3DPSREGISTER_Alpha = 0,
4524 D3DPSREGISTER_BloomBlur_Parameters = 1,
4525 D3DPSREGISTER_ClientTime = 2,
4526 D3DPSREGISTER_Color_Ambient = 3,
4527 D3DPSREGISTER_Color_Diffuse = 4,
4528 D3DPSREGISTER_Color_Specular = 5,
4529 D3DPSREGISTER_Color_Glow = 6,
4530 D3DPSREGISTER_Color_Pants = 7,
4531 D3DPSREGISTER_Color_Shirt = 8,
4532 D3DPSREGISTER_DeferredColor_Ambient = 9,
4533 D3DPSREGISTER_DeferredColor_Diffuse = 10,
4534 D3DPSREGISTER_DeferredColor_Specular = 11,
4535 D3DPSREGISTER_DeferredMod_Diffuse = 12,
4536 D3DPSREGISTER_DeferredMod_Specular = 13,
4537 D3DPSREGISTER_DistortScaleRefractReflect = 14,
4538 D3DPSREGISTER_EyePosition = 15, // unused
4539 D3DPSREGISTER_FogColor = 16,
4540 D3DPSREGISTER_FogHeightFade = 17,
4541 D3DPSREGISTER_FogPlane = 18,
4542 D3DPSREGISTER_FogPlaneViewDist = 19,
4543 D3DPSREGISTER_FogRangeRecip = 20,
4544 D3DPSREGISTER_LightColor = 21,
4545 D3DPSREGISTER_LightDir = 22, // unused
4546 D3DPSREGISTER_LightPosition = 23,
4547 D3DPSREGISTER_OffsetMapping_Scale = 24,
4548 D3DPSREGISTER_PixelSize = 25,
4549 D3DPSREGISTER_ReflectColor = 26,
4550 D3DPSREGISTER_ReflectFactor = 27,
4551 D3DPSREGISTER_ReflectOffset = 28,
4552 D3DPSREGISTER_RefractColor = 29,
4553 D3DPSREGISTER_Saturation = 30,
4554 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4555 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4556 D3DPSREGISTER_ScreenToDepth = 33,
4557 D3DPSREGISTER_ShadowMap_Parameters = 34,
4558 D3DPSREGISTER_ShadowMap_TextureScale = 35,
4559 D3DPSREGISTER_SpecularPower = 36,
4560 D3DPSREGISTER_UserVec1 = 37,
4561 D3DPSREGISTER_UserVec2 = 38,
4562 D3DPSREGISTER_UserVec3 = 39,
4563 D3DPSREGISTER_UserVec4 = 40,
4564 D3DPSREGISTER_ViewTintColor = 41,
4565 D3DPSREGISTER_PixelToScreenTexCoord = 42,
4566 D3DPSREGISTER_BloomColorSubtract = 43,
4567 D3DPSREGISTER_ViewToLight = 44, // float4x4
4568 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4569 D3DPSREGISTER_NormalmapScrollBlend = 52,
4574 /// information about each possible shader permutation
4575 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4576 /// currently selected permutation
4577 r_hlsl_permutation_t *r_hlsl_permutation;
4578 /// storage for permutations linked in the hash table
4579 memexpandablearray_t r_hlsl_permutationarray;
4581 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4583 //unsigned int hashdepth = 0;
4584 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4585 r_hlsl_permutation_t *p;
4586 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4588 if (p->mode == mode && p->permutation == permutation)
4590 //if (hashdepth > 10)
4591 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4596 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4598 p->permutation = permutation;
4599 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4600 r_hlsl_permutationhash[mode][hashindex] = p;
4601 //if (hashdepth > 10)
4602 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4606 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4609 if (!filename || !filename[0])
4611 if (!strcmp(filename, "hlsl/default.hlsl"))
4613 if (!hlslshaderstring)
4615 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4616 if (hlslshaderstring)
4617 Con_DPrintf("Loading shaders from file %s...\n", filename);
4619 hlslshaderstring = (char *)builtincgshaderstring;
4621 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4622 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4623 return shaderstring;
4625 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4628 if (printfromdisknotice)
4629 Con_DPrintf("from disk %s... ", filename);
4630 return shaderstring;
4632 return shaderstring;
4636 //#include <d3dx9shader.h>
4637 //#include <d3dx9mesh.h>
4639 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4641 DWORD *vsbin = NULL;
4642 DWORD *psbin = NULL;
4643 fs_offset_t vsbinsize;
4644 fs_offset_t psbinsize;
4645 // IDirect3DVertexShader9 *vs = NULL;
4646 // IDirect3DPixelShader9 *ps = NULL;
4647 ID3DXBuffer *vslog = NULL;
4648 ID3DXBuffer *vsbuffer = NULL;
4649 ID3DXConstantTable *vsconstanttable = NULL;
4650 ID3DXBuffer *pslog = NULL;
4651 ID3DXBuffer *psbuffer = NULL;
4652 ID3DXConstantTable *psconstanttable = NULL;
4655 char temp[MAX_INPUTLINE];
4656 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4657 qboolean debugshader = gl_paranoid.integer != 0;
4658 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4659 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4662 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4663 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4665 if ((!vsbin && vertstring) || (!psbin && fragstring))
4667 const char* dllnames_d3dx9 [] =
4691 dllhandle_t d3dx9_dll = NULL;
4692 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4693 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4694 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4695 dllfunction_t d3dx9_dllfuncs[] =
4697 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
4698 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
4699 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
4702 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4704 DWORD shaderflags = 0;
4706 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4707 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4708 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4709 if (vertstring && vertstring[0])
4713 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4714 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4715 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4716 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4719 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4722 vsbinsize = vsbuffer->GetBufferSize();
4723 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4724 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4725 vsbuffer->Release();
4729 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4730 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4734 if (fragstring && fragstring[0])
4738 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4739 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4740 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4741 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4744 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4747 psbinsize = psbuffer->GetBufferSize();
4748 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4749 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4750 psbuffer->Release();
4754 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4755 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4759 Sys_UnloadLibrary(&d3dx9_dll);
4762 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4766 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4767 if (FAILED(vsresult))
4768 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4769 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4770 if (FAILED(psresult))
4771 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4773 // free the shader data
4774 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4775 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4778 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4781 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4782 int vertstring_length = 0;
4783 int geomstring_length = 0;
4784 int fragstring_length = 0;
4786 char *vertexstring, *geometrystring, *fragmentstring;
4787 char *vertstring, *geomstring, *fragstring;
4788 char permutationname[256];
4789 char cachename[256];
4790 int vertstrings_count = 0;
4791 int geomstrings_count = 0;
4792 int fragstrings_count = 0;
4793 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4794 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4795 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4800 p->vertexshader = NULL;
4801 p->pixelshader = NULL;
4803 permutationname[0] = 0;
4805 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
4806 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4807 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4809 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4810 strlcat(cachename, "hlsl/", sizeof(cachename));
4812 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4813 vertstrings_count = 0;
4814 geomstrings_count = 0;
4815 fragstrings_count = 0;
4816 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4817 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4818 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4820 // the first pretext is which type of shader to compile as
4821 // (later these will all be bound together as a program object)
4822 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4823 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4824 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4826 // the second pretext is the mode (for example a light source)
4827 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4828 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4829 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4830 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4831 strlcat(cachename, modeinfo->name, sizeof(cachename));
4833 // now add all the permutation pretexts
4834 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4836 if (permutation & (1<<i))
4838 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4839 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4840 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4841 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4842 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4846 // keep line numbers correct
4847 vertstrings_list[vertstrings_count++] = "\n";
4848 geomstrings_list[geomstrings_count++] = "\n";
4849 fragstrings_list[fragstrings_count++] = "\n";
4854 R_CompileShader_AddStaticParms(mode, permutation);
4855 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4856 vertstrings_count += shaderstaticparms_count;
4857 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4858 geomstrings_count += shaderstaticparms_count;
4859 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4860 fragstrings_count += shaderstaticparms_count;
4862 // replace spaces in the cachename with _ characters
4863 for (i = 0;cachename[i];i++)
4864 if (cachename[i] == ' ')
4867 // now append the shader text itself
4868 vertstrings_list[vertstrings_count++] = vertexstring;
4869 geomstrings_list[geomstrings_count++] = geometrystring;
4870 fragstrings_list[fragstrings_count++] = fragmentstring;
4872 // if any sources were NULL, clear the respective list
4874 vertstrings_count = 0;
4875 if (!geometrystring)
4876 geomstrings_count = 0;
4877 if (!fragmentstring)
4878 fragstrings_count = 0;
4880 vertstring_length = 0;
4881 for (i = 0;i < vertstrings_count;i++)
4882 vertstring_length += strlen(vertstrings_list[i]);
4883 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4884 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4885 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4887 geomstring_length = 0;
4888 for (i = 0;i < geomstrings_count;i++)
4889 geomstring_length += strlen(geomstrings_list[i]);
4890 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4891 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4892 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4894 fragstring_length = 0;
4895 for (i = 0;i < fragstrings_count;i++)
4896 fragstring_length += strlen(fragstrings_list[i]);
4897 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4898 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4899 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4901 // try to load the cached shader, or generate one
4902 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4904 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4905 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4907 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
4911 Mem_Free(vertstring);
4913 Mem_Free(geomstring);
4915 Mem_Free(fragstring);
4917 Mem_Free(vertexstring);
4919 Mem_Free(geometrystring);
4921 Mem_Free(fragmentstring);
4924 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4925 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4926 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);}
4927 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);}
4928 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);}
4929 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);}
4931 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4932 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4933 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);}
4934 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);}
4935 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);}
4936 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);}
4938 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4940 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4941 if (r_hlsl_permutation != perm)
4943 r_hlsl_permutation = perm;
4944 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4946 if (!r_hlsl_permutation->compiled)
4947 R_HLSL_CompilePermutation(perm, mode, permutation);
4948 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4950 // remove features until we find a valid permutation
4952 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4954 // reduce i more quickly whenever it would not remove any bits
4955 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4956 if (!(permutation & j))
4959 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4960 if (!r_hlsl_permutation->compiled)
4961 R_HLSL_CompilePermutation(perm, mode, permutation);
4962 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4965 if (i >= SHADERPERMUTATION_COUNT)
4967 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4968 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4969 return; // no bit left to clear, entire mode is broken
4973 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4974 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4976 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4977 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4978 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4982 void R_GLSL_Restart_f(void)
4984 unsigned int i, limit;
4985 if (glslshaderstring && glslshaderstring != builtinshaderstring)
4986 Mem_Free(glslshaderstring);
4987 glslshaderstring = NULL;
4988 if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4989 Mem_Free(cgshaderstring);
4990 cgshaderstring = NULL;
4991 if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
4992 Mem_Free(hlslshaderstring);
4993 hlslshaderstring = NULL;
4994 switch(vid.renderpath)
4996 case RENDERPATH_D3D9:
4999 r_hlsl_permutation_t *p;
5000 r_hlsl_permutation = NULL;
5001 // cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5002 // cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5003 // cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5004 // cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5005 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
5006 for (i = 0;i < limit;i++)
5008 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
5010 if (p->vertexshader)
5011 IDirect3DVertexShader9_Release(p->vertexshader);
5013 IDirect3DPixelShader9_Release(p->pixelshader);
5014 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
5017 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
5021 case RENDERPATH_D3D10:
5022 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5024 case RENDERPATH_D3D11:
5025 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5027 case RENDERPATH_GL20:
5029 r_glsl_permutation_t *p;
5030 r_glsl_permutation = NULL;
5031 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
5032 for (i = 0;i < limit;i++)
5034 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
5036 GL_Backend_FreeProgram(p->program);
5037 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
5040 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5043 case RENDERPATH_CGGL:
5046 r_cg_permutation_t *p;
5047 r_cg_permutation = NULL;
5048 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5049 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5050 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5051 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5052 limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
5053 for (i = 0;i < limit;i++)
5055 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
5058 cgDestroyProgram(p->vprogram);
5060 cgDestroyProgram(p->fprogram);
5061 Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
5064 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5068 case RENDERPATH_GL13:
5069 case RENDERPATH_GL11:
5074 void R_GLSL_DumpShader_f(void)
5079 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
5082 FS_Print(file, "/* The engine may define the following macros:\n");
5083 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5084 for (i = 0;i < SHADERMODE_COUNT;i++)
5085 FS_Print(file, glslshadermodeinfo[i].pretext);
5086 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5087 FS_Print(file, shaderpermutationinfo[i].pretext);
5088 FS_Print(file, "*/\n");
5089 FS_Print(file, builtinshaderstring);
5091 Con_Printf("glsl/default.glsl written\n");
5094 Con_Printf("failed to write to glsl/default.glsl\n");
5097 file = FS_OpenRealFile("cg/default.cg", "w", false);
5100 FS_Print(file, "/* The engine may define the following macros:\n");
5101 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5102 for (i = 0;i < SHADERMODE_COUNT;i++)
5103 FS_Print(file, cgshadermodeinfo[i].pretext);
5104 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5105 FS_Print(file, shaderpermutationinfo[i].pretext);
5106 FS_Print(file, "*/\n");
5107 FS_Print(file, builtincgshaderstring);
5109 Con_Printf("cg/default.cg written\n");
5112 Con_Printf("failed to write to cg/default.cg\n");
5116 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
5119 FS_Print(file, "/* The engine may define the following macros:\n");
5120 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5121 for (i = 0;i < SHADERMODE_COUNT;i++)
5122 FS_Print(file, hlslshadermodeinfo[i].pretext);
5123 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5124 FS_Print(file, shaderpermutationinfo[i].pretext);
5125 FS_Print(file, "*/\n");
5126 FS_Print(file, builtincgshaderstring);
5128 Con_Printf("hlsl/default.hlsl written\n");
5131 Con_Printf("failed to write to hlsl/default.hlsl\n");
5135 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
5138 texturemode = GL_MODULATE;
5139 switch (vid.renderpath)
5141 case RENDERPATH_D3D9:
5143 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))));
5144 R_Mesh_TexBind(GL20TU_FIRST , first );
5145 R_Mesh_TexBind(GL20TU_SECOND, second);
5148 case RENDERPATH_D3D10:
5149 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5151 case RENDERPATH_D3D11:
5152 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5154 case RENDERPATH_GL20:
5155 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))));
5156 R_Mesh_TexBind(GL20TU_FIRST , first );
5157 R_Mesh_TexBind(GL20TU_SECOND, second);
5159 case RENDERPATH_CGGL:
5162 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))));
5163 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
5164 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
5167 case RENDERPATH_GL13:
5168 R_Mesh_TexBind(0, first );
5169 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
5170 R_Mesh_TexBind(1, second);
5172 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
5174 case RENDERPATH_GL11:
5175 R_Mesh_TexBind(0, first );
5180 void R_SetupShader_DepthOrShadow(void)
5182 switch (vid.renderpath)
5184 case RENDERPATH_D3D9:
5186 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5189 case RENDERPATH_D3D10:
5190 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5192 case RENDERPATH_D3D11:
5193 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5195 case RENDERPATH_GL20:
5196 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5198 case RENDERPATH_CGGL:
5200 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5203 case RENDERPATH_GL13:
5204 R_Mesh_TexBind(0, 0);
5205 R_Mesh_TexBind(1, 0);
5207 case RENDERPATH_GL11:
5208 R_Mesh_TexBind(0, 0);
5213 void R_SetupShader_ShowDepth(void)
5215 switch (vid.renderpath)
5217 case RENDERPATH_D3D9:
5219 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5222 case RENDERPATH_D3D10:
5223 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5225 case RENDERPATH_D3D11:
5226 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5228 case RENDERPATH_GL20:
5229 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5231 case RENDERPATH_CGGL:
5233 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5236 case RENDERPATH_GL13:
5238 case RENDERPATH_GL11:
5243 extern qboolean r_shadow_usingdeferredprepass;
5244 extern cvar_t r_shadow_deferred_8bitrange;
5245 extern rtexture_t *r_shadow_attenuationgradienttexture;
5246 extern rtexture_t *r_shadow_attenuation2dtexture;
5247 extern rtexture_t *r_shadow_attenuation3dtexture;
5248 extern qboolean r_shadow_usingshadowmap2d;
5249 extern qboolean r_shadow_usingshadowmaportho;
5250 extern float r_shadow_shadowmap_texturescale[2];
5251 extern float r_shadow_shadowmap_parameters[4];
5252 extern qboolean r_shadow_shadowmapvsdct;
5253 extern qboolean r_shadow_shadowmapsampler;
5254 extern int r_shadow_shadowmappcf;
5255 extern rtexture_t *r_shadow_shadowmap2dtexture;
5256 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5257 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5258 extern matrix4x4_t r_shadow_shadowmapmatrix;
5259 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5260 extern int r_shadow_prepass_width;
5261 extern int r_shadow_prepass_height;
5262 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5263 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5264 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
5265 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5266 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5267 extern cvar_t gl_mesh_separatearrays;
5268 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5270 // a blendfunc allows colormod if:
5271 // a) it can never keep the destination pixel invariant, or
5272 // b) it can keep the destination pixel invariant, and still can do so if colormodded
5273 // this is to prevent unintended side effects from colormod
5276 // IF there is a (s, sa) for which for all (d, da),
5277 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5278 // THEN, for this (s, sa) and all (colormod, d, da):
5279 // s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5280 // OBVIOUSLY, this means that
5281 // s*colormod * src(s*colormod, d, sa, da) = 0
5282 // dst(s*colormod, d, sa, da) = 1
5284 // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5286 // main condition to leave dst color invariant:
5287 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5289 // s * 0 + d * dst(s, d, sa, da) == d
5290 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5291 // => colormod is a problem for GL_SRC_COLOR only
5293 // s + d * dst(s, d, sa, da) == d
5295 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5296 // => colormod is never problematic for these
5297 // src == GL_SRC_COLOR:
5298 // s*s + d * dst(s, d, sa, da) == d
5300 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5301 // => colormod is never problematic for these
5302 // src == GL_ONE_MINUS_SRC_COLOR:
5303 // s*(1-s) + d * dst(s, d, sa, da) == d
5304 // => s == 0 or s == 1
5305 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5306 // => colormod is a problem for GL_SRC_COLOR only
5307 // src == GL_DST_COLOR
5308 // s*d + d * dst(s, d, sa, da) == d
5310 // => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5311 // => colormod is always a problem
5314 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5315 // => colormod is never problematic for these
5316 // => BUT, we do not know s! We must assume it is problematic
5317 // then... except in GL_ONE case, where we know all invariant
5319 // src == GL_ONE_MINUS_DST_COLOR
5320 // s*(1-d) + d * dst(s, d, sa, da) == d
5321 // => s == 0 (1-d is impossible to handle for our desired result)
5322 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5323 // => colormod is never problematic for these
5324 // src == GL_SRC_ALPHA
5325 // s*sa + d * dst(s, d, sa, da) == d
5326 // => s == 0, or sa == 0
5327 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5328 // => colormod breaks in the case GL_SRC_COLOR only
5329 // src == GL_ONE_MINUS_SRC_ALPHA
5330 // s*(1-sa) + d * dst(s, d, sa, da) == d
5331 // => s == 0, or sa == 1
5332 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5333 // => colormod breaks in the case GL_SRC_COLOR only
5334 // src == GL_DST_ALPHA
5335 // s*da + d * dst(s, d, sa, da) == d
5337 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5338 // => colormod is never problematic for these
5343 case GL_ONE_MINUS_SRC_COLOR:
5345 case GL_ONE_MINUS_SRC_ALPHA:
5346 if(dst == GL_SRC_COLOR)
5351 case GL_ONE_MINUS_DST_COLOR:
5353 case GL_ONE_MINUS_DST_ALPHA:
5363 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)
5365 // select a permutation of the lighting shader appropriate to this
5366 // combination of texture, entity, light source, and fogging, only use the
5367 // minimum features necessary to avoid wasting rendering time in the
5368 // fragment shader on features that are not being used
5369 unsigned int permutation = 0;
5370 unsigned int mode = 0;
5371 qboolean allow_colormod;
5372 static float dummy_colormod[3] = {1, 1, 1};
5373 float *colormod = rsurface.colormod;
5375 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5376 if (rsurfacepass == RSURFPASS_BACKGROUND)
5378 // distorted background
5379 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5381 mode = SHADERMODE_WATER;
5382 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
5383 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
5384 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5385 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5387 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5389 mode = SHADERMODE_REFRACTION;
5390 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5391 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5395 mode = SHADERMODE_GENERIC;
5396 permutation |= SHADERPERMUTATION_DIFFUSE;
5397 GL_BlendFunc(GL_ONE, GL_ZERO);
5398 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5400 GL_AlphaTest(false);
5402 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5404 if (r_glsl_offsetmapping.integer)
5406 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5407 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5408 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5409 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5410 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5412 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5413 if (r_glsl_offsetmapping_reliefmapping.integer)
5414 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5417 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5418 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5419 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5420 permutation |= SHADERPERMUTATION_ALPHAKILL;
5421 // normalmap (deferred prepass), may use alpha test on diffuse
5422 mode = SHADERMODE_DEFERREDGEOMETRY;
5423 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5424 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5425 GL_AlphaTest(false);
5426 GL_BlendFunc(GL_ONE, GL_ZERO);
5427 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5429 else if (rsurfacepass == RSURFPASS_RTLIGHT)
5431 if (r_glsl_offsetmapping.integer)
5433 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5434 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5435 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5436 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5437 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5439 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5440 if (r_glsl_offsetmapping_reliefmapping.integer)
5441 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5444 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5445 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5447 mode = SHADERMODE_LIGHTSOURCE;
5448 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5449 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5450 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5451 permutation |= SHADERPERMUTATION_CUBEFILTER;
5452 if (diffusescale > 0)
5453 permutation |= SHADERPERMUTATION_DIFFUSE;
5454 if (specularscale > 0)
5455 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5456 if (r_refdef.fogenabled)
5457 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5458 if (rsurface.texture->colormapping)
5459 permutation |= SHADERPERMUTATION_COLORMAPPING;
5460 if (r_shadow_usingshadowmap2d)
5462 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5463 if(r_shadow_shadowmapvsdct)
5464 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5466 if (r_shadow_shadowmapsampler)
5467 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5468 if (r_shadow_shadowmappcf > 1)
5469 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5470 else if (r_shadow_shadowmappcf)
5471 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5473 if (rsurface.texture->reflectmasktexture)
5474 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5475 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5476 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5477 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5479 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5481 if (r_glsl_offsetmapping.integer)
5483 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5484 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5485 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5486 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5487 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5489 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5490 if (r_glsl_offsetmapping_reliefmapping.integer)
5491 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5494 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5495 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5496 // unshaded geometry (fullbright or ambient model lighting)
5497 mode = SHADERMODE_FLATCOLOR;
5498 ambientscale = diffusescale = specularscale = 0;
5499 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5500 permutation |= SHADERPERMUTATION_GLOW;
5501 if (r_refdef.fogenabled)
5502 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5503 if (rsurface.texture->colormapping)
5504 permutation |= SHADERPERMUTATION_COLORMAPPING;
5505 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5507 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5508 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5510 if (r_shadow_shadowmapsampler)
5511 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5512 if (r_shadow_shadowmappcf > 1)
5513 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5514 else if (r_shadow_shadowmappcf)
5515 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5517 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5518 permutation |= SHADERPERMUTATION_REFLECTION;
5519 if (rsurface.texture->reflectmasktexture)
5520 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5521 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5522 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5523 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5525 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5527 if (r_glsl_offsetmapping.integer)
5529 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5530 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5531 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5532 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5533 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5535 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5536 if (r_glsl_offsetmapping_reliefmapping.integer)
5537 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5540 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5541 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5542 // directional model lighting
5543 mode = SHADERMODE_LIGHTDIRECTION;
5544 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5545 permutation |= SHADERPERMUTATION_GLOW;
5546 permutation |= SHADERPERMUTATION_DIFFUSE;
5547 if (specularscale > 0)
5548 permutation |= SHADERPERMUTATION_SPECULAR;
5549 if (r_refdef.fogenabled)
5550 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5551 if (rsurface.texture->colormapping)
5552 permutation |= SHADERPERMUTATION_COLORMAPPING;
5553 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5555 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5556 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5558 if (r_shadow_shadowmapsampler)
5559 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5560 if (r_shadow_shadowmappcf > 1)
5561 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5562 else if (r_shadow_shadowmappcf)
5563 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5565 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5566 permutation |= SHADERPERMUTATION_REFLECTION;
5567 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5568 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5569 if (rsurface.texture->reflectmasktexture)
5570 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5571 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5572 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5573 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5575 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5577 if (r_glsl_offsetmapping.integer)
5579 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5580 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5581 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5582 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5583 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5585 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5586 if (r_glsl_offsetmapping_reliefmapping.integer)
5587 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5590 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5591 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5592 // ambient model lighting
5593 mode = SHADERMODE_LIGHTDIRECTION;
5594 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5595 permutation |= SHADERPERMUTATION_GLOW;
5596 if (r_refdef.fogenabled)
5597 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5598 if (rsurface.texture->colormapping)
5599 permutation |= SHADERPERMUTATION_COLORMAPPING;
5600 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5602 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5603 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5605 if (r_shadow_shadowmapsampler)
5606 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5607 if (r_shadow_shadowmappcf > 1)
5608 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5609 else if (r_shadow_shadowmappcf)
5610 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5612 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5613 permutation |= SHADERPERMUTATION_REFLECTION;
5614 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5615 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5616 if (rsurface.texture->reflectmasktexture)
5617 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5618 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5619 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5620 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5624 if (r_glsl_offsetmapping.integer)
5626 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5627 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5628 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5629 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5630 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5632 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5633 if (r_glsl_offsetmapping_reliefmapping.integer)
5634 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5637 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5638 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5640 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5641 permutation |= SHADERPERMUTATION_GLOW;
5642 if (r_refdef.fogenabled)
5643 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5644 if (rsurface.texture->colormapping)
5645 permutation |= SHADERPERMUTATION_COLORMAPPING;
5646 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5648 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5649 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5651 if (r_shadow_shadowmapsampler)
5652 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5653 if (r_shadow_shadowmappcf > 1)
5654 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5655 else if (r_shadow_shadowmappcf)
5656 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5658 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5659 permutation |= SHADERPERMUTATION_REFLECTION;
5660 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5661 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5662 if (rsurface.texture->reflectmasktexture)
5663 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5664 if (FAKELIGHT_ENABLED)
5666 // fake lightmapping (q1bsp, q3bsp, fullbright map)
5667 mode = SHADERMODE_FAKELIGHT;
5668 permutation |= SHADERPERMUTATION_DIFFUSE;
5669 if (specularscale > 0)
5670 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5672 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5674 // deluxemapping (light direction texture)
5675 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5676 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5678 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5679 permutation |= SHADERPERMUTATION_DIFFUSE;
5680 if (specularscale > 0)
5681 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5683 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5685 // fake deluxemapping (uniform light direction in tangentspace)
5686 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5687 permutation |= SHADERPERMUTATION_DIFFUSE;
5688 if (specularscale > 0)
5689 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5691 else if (rsurface.uselightmaptexture)
5693 // ordinary lightmapping (q1bsp, q3bsp)
5694 mode = SHADERMODE_LIGHTMAP;
5698 // ordinary vertex coloring (q3bsp)
5699 mode = SHADERMODE_VERTEXCOLOR;
5701 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5702 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5703 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5706 colormod = dummy_colormod;
5707 switch(vid.renderpath)
5709 case RENDERPATH_D3D9:
5711 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);
5712 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5713 R_SetupShader_SetPermutationHLSL(mode, permutation);
5714 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5715 if (mode == SHADERMODE_LIGHTSOURCE)
5717 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5718 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5722 if (mode == SHADERMODE_LIGHTDIRECTION)
5724 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5727 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5728 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5729 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5730 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5731 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5733 if (mode == SHADERMODE_LIGHTSOURCE)
5735 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5736 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5737 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5738 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5739 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5741 // additive passes are only darkened by fog, not tinted
5742 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5743 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5747 if (mode == SHADERMODE_FLATCOLOR)
5749 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5751 else if (mode == SHADERMODE_LIGHTDIRECTION)
5753 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]);
5754 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5755 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);
5756 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);
5757 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5758 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5759 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5763 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5764 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5765 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);
5766 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);
5767 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5769 // additive passes are only darkened by fog, not tinted
5770 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5771 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5773 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5774 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);
5775 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5776 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5777 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5778 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5779 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5780 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5781 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5782 if (mode == SHADERMODE_WATER)
5783 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5785 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5786 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5787 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5788 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));
5789 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5790 if (rsurface.texture->pantstexture)
5791 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5793 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5794 if (rsurface.texture->shirttexture)
5795 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5797 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5798 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5799 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5800 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5801 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5802 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5803 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5804 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5806 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5807 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5808 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5809 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5810 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5811 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5812 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5813 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5814 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5815 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5816 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5817 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5818 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5819 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5820 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5821 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5822 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5823 if (rsurfacepass == RSURFPASS_BACKGROUND)
5825 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5826 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5827 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5831 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5833 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5834 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5835 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5836 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5837 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5839 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5840 if (rsurface.rtlight)
5842 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5843 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5848 case RENDERPATH_D3D10:
5849 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5851 case RENDERPATH_D3D11:
5852 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5854 case RENDERPATH_GL20:
5855 if (gl_mesh_separatearrays.integer)
5857 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);
5858 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5859 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5860 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5861 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5862 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5863 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5864 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5868 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);
5869 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5871 R_SetupShader_SetPermutationGLSL(mode, permutation);
5872 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5873 if (mode == SHADERMODE_LIGHTSOURCE)
5875 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5876 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5877 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5878 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5879 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5880 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);
5882 // additive passes are only darkened by fog, not tinted
5883 if (r_glsl_permutation->loc_FogColor >= 0)
5884 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5885 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5889 if (mode == SHADERMODE_FLATCOLOR)
5891 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5893 else if (mode == SHADERMODE_LIGHTDIRECTION)
5895 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]);
5896 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]);
5897 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);
5898 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);
5899 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);
5900 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]);
5901 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]);
5905 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]);
5906 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]);
5907 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);
5908 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);
5909 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);
5911 // additive passes are only darkened by fog, not tinted
5912 if (r_glsl_permutation->loc_FogColor >= 0)
5914 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5915 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5917 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5919 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);
5920 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]);
5921 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]);
5922 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]);
5923 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]);
5924 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5925 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5926 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5927 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]);
5929 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5930 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5931 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5932 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]);
5933 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]);
5935 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5936 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));
5937 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5938 if (r_glsl_permutation->loc_Color_Pants >= 0)
5940 if (rsurface.texture->pantstexture)
5941 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5943 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5945 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5947 if (rsurface.texture->shirttexture)
5948 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5950 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5952 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]);
5953 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5954 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5955 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5956 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5957 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]);
5958 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5960 // if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_texture_white );
5961 // if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_texture_white );
5962 // if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS , r_texture_gammaramps );
5963 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5964 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5965 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5966 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5967 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5968 if (r_glsl_permutation->loc_Texture_SecondaryColor >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5969 if (r_glsl_permutation->loc_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5970 if (r_glsl_permutation->loc_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5971 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5972 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5973 if (r_glsl_permutation->loc_Texture_ReflectMask >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5974 if (r_glsl_permutation->loc_Texture_ReflectCube >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5975 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5976 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5977 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5978 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5979 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5980 if (rsurfacepass == RSURFPASS_BACKGROUND)
5982 if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5983 else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5984 if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5988 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5990 // if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5991 // if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5992 if (r_glsl_permutation->loc_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5993 if (r_glsl_permutation->loc_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5994 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5996 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture );
5997 if (rsurface.rtlight)
5999 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
6000 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
6005 case RENDERPATH_CGGL:
6007 if (gl_mesh_separatearrays.integer)
6009 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);
6010 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
6011 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
6012 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
6013 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
6014 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
6015 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
6016 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
6020 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);
6021 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
6023 R_SetupShader_SetPermutationCG(mode, permutation);
6024 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
6025 if (mode == SHADERMODE_LIGHTSOURCE)
6027 if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
6028 if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6032 if (mode == SHADERMODE_LIGHTDIRECTION)
6034 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
6037 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
6038 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
6039 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
6040 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6041 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
6044 if (mode == SHADERMODE_LIGHTSOURCE)
6046 if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6047 if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
6048 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
6049 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
6050 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
6052 // additive passes are only darkened by fog, not tinted
6053 if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
6054 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6058 if (mode == SHADERMODE_FLATCOLOR)
6060 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
6062 else if (mode == SHADERMODE_LIGHTDIRECTION)
6064 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
6065 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
6066 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
6067 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
6068 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
6069 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
6070 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
6074 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
6075 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
6076 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
6077 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
6078 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
6080 // additive passes are only darkened by fog, not tinted
6081 if (r_cg_permutation->fp_FogColor)
6083 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6084 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
6086 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6089 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
6090 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
6091 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
6092 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
6093 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
6094 if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
6095 if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
6096 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6097 if (r_cg_permutation->fp_NormalmapScrollBlend) cgGLSetParameter2f(r_cg_permutation->fp_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
6099 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
6100 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
6101 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
6102 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
6103 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6104 if (r_cg_permutation->fp_Color_Pants)
6106 if (rsurface.texture->pantstexture)
6107 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6109 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
6112 if (r_cg_permutation->fp_Color_Shirt)
6114 if (rsurface.texture->shirttexture)
6115 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6117 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
6120 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
6121 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
6122 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
6123 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
6124 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
6125 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
6126 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6128 // if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_texture_white );CHECKCGERROR
6129 // if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_texture_white );CHECKCGERROR
6130 // if (r_cg_permutation->fp_Texture_GammaRamps ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps , r_texture_gammaramps );CHECKCGERROR
6131 if (r_cg_permutation->fp_Texture_Normal ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal , rsurface.texture->nmaptexture );CHECKCGERROR
6132 if (r_cg_permutation->fp_Texture_Color ) CG_BindTexture(r_cg_permutation->fp_Texture_Color , rsurface.texture->basetexture );CHECKCGERROR
6133 if (r_cg_permutation->fp_Texture_Gloss ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss , rsurface.texture->glosstexture );CHECKCGERROR
6134 if (r_cg_permutation->fp_Texture_Glow ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow , rsurface.texture->glowtexture );CHECKCGERROR
6135 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture );CHECKCGERROR
6136 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );CHECKCGERROR
6137 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );CHECKCGERROR
6138 if (r_cg_permutation->fp_Texture_SecondaryGlow ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );CHECKCGERROR
6139 if (r_cg_permutation->fp_Texture_Pants ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants , rsurface.texture->pantstexture );CHECKCGERROR
6140 if (r_cg_permutation->fp_Texture_Shirt ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt , rsurface.texture->shirttexture );CHECKCGERROR
6141 if (r_cg_permutation->fp_Texture_ReflectMask ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask , rsurface.texture->reflectmasktexture );CHECKCGERROR
6142 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
6143 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture );CHECKCGERROR
6144 if (r_cg_permutation->fp_Texture_FogMask ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask , r_texture_fogattenuation );CHECKCGERROR
6145 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
6146 if (r_cg_permutation->fp_Texture_Deluxemap ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
6147 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
6148 if (rsurfacepass == RSURFPASS_BACKGROUND)
6150 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
6151 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
6152 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
6156 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
6158 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
6159 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
6160 if (r_cg_permutation->fp_Texture_ScreenDiffuse ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );CHECKCGERROR
6161 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );CHECKCGERROR
6162 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6164 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
6165 if (rsurface.rtlight)
6167 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
6168 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
6175 case RENDERPATH_GL13:
6176 case RENDERPATH_GL11:
6181 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6183 // select a permutation of the lighting shader appropriate to this
6184 // combination of texture, entity, light source, and fogging, only use the
6185 // minimum features necessary to avoid wasting rendering time in the
6186 // fragment shader on features that are not being used
6187 unsigned int permutation = 0;
6188 unsigned int mode = 0;
6189 const float *lightcolorbase = rtlight->currentcolor;
6190 float ambientscale = rtlight->ambientscale;
6191 float diffusescale = rtlight->diffusescale;
6192 float specularscale = rtlight->specularscale;
6193 // this is the location of the light in view space
6194 vec3_t viewlightorigin;
6195 // this transforms from view space (camera) to light space (cubemap)
6196 matrix4x4_t viewtolight;
6197 matrix4x4_t lighttoview;
6198 float viewtolight16f[16];
6199 float range = 1.0f / r_shadow_deferred_8bitrange.value;
6201 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6202 if (rtlight->currentcubemap != r_texture_whitecube)
6203 permutation |= SHADERPERMUTATION_CUBEFILTER;
6204 if (diffusescale > 0)
6205 permutation |= SHADERPERMUTATION_DIFFUSE;
6206 if (specularscale > 0)
6207 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6208 if (r_shadow_usingshadowmap2d)
6210 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6211 if (r_shadow_shadowmapvsdct)
6212 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6214 if (r_shadow_shadowmapsampler)
6215 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6216 if (r_shadow_shadowmappcf > 1)
6217 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6218 else if (r_shadow_shadowmappcf)
6219 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6221 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6222 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6223 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6224 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6225 switch(vid.renderpath)
6227 case RENDERPATH_D3D9:
6229 R_SetupShader_SetPermutationHLSL(mode, permutation);
6230 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6231 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6232 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
6233 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
6234 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6235 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6236 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6237 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6238 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6239 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6241 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
6242 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
6243 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
6244 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
6245 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
6246 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
6249 case RENDERPATH_D3D10:
6250 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6252 case RENDERPATH_D3D11:
6253 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6255 case RENDERPATH_GL20:
6256 R_SetupShader_SetPermutationGLSL(mode, permutation);
6257 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6258 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
6259 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);
6260 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);
6261 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);
6262 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]);
6263 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]);
6264 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));
6265 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]);
6266 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6268 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
6269 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
6270 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
6271 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
6272 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
6273 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
6275 case RENDERPATH_CGGL:
6277 R_SetupShader_SetPermutationCG(mode, permutation);
6278 if (r_cg_permutation->fp_LightPosition ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6279 if (r_cg_permutation->fp_ViewToLight ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6280 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
6281 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
6282 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
6283 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
6284 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
6285 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
6286 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
6287 if (r_cg_permutation->fp_PixelToScreenTexCoord ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6289 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
6290 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
6291 if (r_cg_permutation->fp_Texture_ScreenNormalMap ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
6292 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
6293 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
6294 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
6297 case RENDERPATH_GL13:
6298 case RENDERPATH_GL11:
6303 #define SKINFRAME_HASH 1024
6307 int loadsequence; // incremented each level change
6308 memexpandablearray_t array;
6309 skinframe_t *hash[SKINFRAME_HASH];
6312 r_skinframe_t r_skinframe;
6314 void R_SkinFrame_PrepareForPurge(void)
6316 r_skinframe.loadsequence++;
6317 // wrap it without hitting zero
6318 if (r_skinframe.loadsequence >= 200)
6319 r_skinframe.loadsequence = 1;
6322 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6326 // mark the skinframe as used for the purging code
6327 skinframe->loadsequence = r_skinframe.loadsequence;
6330 void R_SkinFrame_Purge(void)
6334 for (i = 0;i < SKINFRAME_HASH;i++)
6336 for (s = r_skinframe.hash[i];s;s = s->next)
6338 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6340 if (s->merged == s->base)
6342 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6343 R_PurgeTexture(s->stain );s->stain = NULL;
6344 R_PurgeTexture(s->merged);s->merged = NULL;
6345 R_PurgeTexture(s->base );s->base = NULL;
6346 R_PurgeTexture(s->pants );s->pants = NULL;
6347 R_PurgeTexture(s->shirt );s->shirt = NULL;
6348 R_PurgeTexture(s->nmap );s->nmap = NULL;
6349 R_PurgeTexture(s->gloss );s->gloss = NULL;
6350 R_PurgeTexture(s->glow );s->glow = NULL;
6351 R_PurgeTexture(s->fog );s->fog = NULL;
6352 R_PurgeTexture(s->reflect);s->reflect = NULL;
6353 s->loadsequence = 0;
6359 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6361 char basename[MAX_QPATH];
6363 Image_StripImageExtension(name, basename, sizeof(basename));
6365 if( last == NULL ) {
6367 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6368 item = r_skinframe.hash[hashindex];
6373 // linearly search through the hash bucket
6374 for( ; item ; item = item->next ) {
6375 if( !strcmp( item->basename, basename ) ) {
6382 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6386 char basename[MAX_QPATH];
6388 Image_StripImageExtension(name, basename, sizeof(basename));
6390 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6391 for (item = r_skinframe.hash[hashindex];item;item = item->next)
6392 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6396 rtexture_t *dyntexture;
6397 // check whether its a dynamic texture
6398 dyntexture = CL_GetDynTexture( basename );
6399 if (!add && !dyntexture)
6401 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6402 memset(item, 0, sizeof(*item));
6403 strlcpy(item->basename, basename, sizeof(item->basename));
6404 item->base = dyntexture; // either NULL or dyntexture handle
6405 item->textureflags = textureflags;
6406 item->comparewidth = comparewidth;
6407 item->compareheight = compareheight;
6408 item->comparecrc = comparecrc;
6409 item->next = r_skinframe.hash[hashindex];
6410 r_skinframe.hash[hashindex] = item;
6412 else if( item->base == NULL )
6414 rtexture_t *dyntexture;
6415 // check whether its a dynamic texture
6416 // 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]
6417 dyntexture = CL_GetDynTexture( basename );
6418 item->base = dyntexture; // either NULL or dyntexture handle
6421 R_SkinFrame_MarkUsed(item);
6425 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6427 unsigned long long avgcolor[5], wsum; \
6435 for(pix = 0; pix < cnt; ++pix) \
6438 for(comp = 0; comp < 3; ++comp) \
6440 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6443 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6445 for(comp = 0; comp < 3; ++comp) \
6446 avgcolor[comp] += getpixel * w; \
6449 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6450 avgcolor[4] += getpixel; \
6452 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6454 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6455 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6456 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6457 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6460 extern cvar_t gl_picmip;
6461 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6464 unsigned char *pixels;
6465 unsigned char *bumppixels;
6466 unsigned char *basepixels = NULL;
6467 int basepixels_width = 0;
6468 int basepixels_height = 0;
6469 skinframe_t *skinframe;
6470 rtexture_t *ddsbase = NULL;
6471 qboolean ddshasalpha = false;
6472 float ddsavgcolor[4];
6473 char basename[MAX_QPATH];
6474 int miplevel = R_PicmipForFlags(textureflags);
6475 int savemiplevel = miplevel;
6478 if (cls.state == ca_dedicated)
6481 // return an existing skinframe if already loaded
6482 // if loading of the first image fails, don't make a new skinframe as it
6483 // would cause all future lookups of this to be missing
6484 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6485 if (skinframe && skinframe->base)
6488 Image_StripImageExtension(name, basename, sizeof(basename));
6490 // check for DDS texture file first
6491 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6493 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6494 if (basepixels == NULL)
6498 // FIXME handle miplevel
6500 if (developer_loading.integer)
6501 Con_Printf("loading skin \"%s\"\n", name);
6503 // we've got some pixels to store, so really allocate this new texture now
6505 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6506 skinframe->stain = NULL;
6507 skinframe->merged = NULL;
6508 skinframe->base = NULL;
6509 skinframe->pants = NULL;
6510 skinframe->shirt = NULL;
6511 skinframe->nmap = NULL;
6512 skinframe->gloss = NULL;
6513 skinframe->glow = NULL;
6514 skinframe->fog = NULL;
6515 skinframe->reflect = NULL;
6516 skinframe->hasalpha = false;
6520 skinframe->base = ddsbase;
6521 skinframe->hasalpha = ddshasalpha;
6522 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6523 if (r_loadfog && skinframe->hasalpha)
6524 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6525 //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]);
6529 basepixels_width = image_width;
6530 basepixels_height = image_height;
6531 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);
6532 if (textureflags & TEXF_ALPHA)
6534 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6536 if (basepixels[j] < 255)
6538 skinframe->hasalpha = true;
6542 if (r_loadfog && skinframe->hasalpha)
6544 // has transparent pixels
6545 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6546 for (j = 0;j < image_width * image_height * 4;j += 4)
6551 pixels[j+3] = basepixels[j+3];
6553 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);
6557 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6558 //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]);
6559 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6560 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6561 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6562 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6567 mymiplevel = savemiplevel;
6568 if (r_loadnormalmap)
6569 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);
6570 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6572 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6573 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6574 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6575 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6578 // _norm is the name used by tenebrae and has been adopted as standard
6579 if (r_loadnormalmap && skinframe->nmap == NULL)
6581 mymiplevel = savemiplevel;
6582 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6584 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);
6588 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6590 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6591 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6592 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);
6594 Mem_Free(bumppixels);
6596 else if (r_shadow_bumpscale_basetexture.value > 0)
6598 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6599 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6600 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);
6603 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6604 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6607 // _luma is supported only for tenebrae compatibility
6608 // _glow is the preferred name
6609 mymiplevel = savemiplevel;
6610 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))))
6612 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);
6613 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6614 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6615 Mem_Free(pixels);pixels = NULL;
6618 mymiplevel = savemiplevel;
6619 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6621 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);
6622 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6623 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6628 mymiplevel = savemiplevel;
6629 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6631 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);
6632 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6633 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6638 mymiplevel = savemiplevel;
6639 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6641 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);
6642 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6643 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6648 mymiplevel = savemiplevel;
6649 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6651 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);
6652 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6653 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6659 Mem_Free(basepixels);
6664 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6665 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6668 unsigned char *temp1, *temp2;
6669 skinframe_t *skinframe;
6671 if (cls.state == ca_dedicated)
6674 // if already loaded just return it, otherwise make a new skinframe
6675 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6676 if (skinframe && skinframe->base)
6679 skinframe->stain = NULL;
6680 skinframe->merged = NULL;
6681 skinframe->base = NULL;
6682 skinframe->pants = NULL;
6683 skinframe->shirt = NULL;
6684 skinframe->nmap = NULL;
6685 skinframe->gloss = NULL;
6686 skinframe->glow = NULL;
6687 skinframe->fog = NULL;
6688 skinframe->reflect = NULL;
6689 skinframe->hasalpha = false;
6691 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6695 if (developer_loading.integer)
6696 Con_Printf("loading 32bit skin \"%s\"\n", name);
6698 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6700 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6701 temp2 = temp1 + width * height * 4;
6702 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6703 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);
6706 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6707 if (textureflags & TEXF_ALPHA)
6709 for (i = 3;i < width * height * 4;i += 4)
6711 if (skindata[i] < 255)
6713 skinframe->hasalpha = true;
6717 if (r_loadfog && skinframe->hasalpha)
6719 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6720 memcpy(fogpixels, skindata, width * height * 4);
6721 for (i = 0;i < width * height * 4;i += 4)
6722 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6723 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6724 Mem_Free(fogpixels);
6728 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6729 //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]);
6734 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6738 skinframe_t *skinframe;
6740 if (cls.state == ca_dedicated)
6743 // if already loaded just return it, otherwise make a new skinframe
6744 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6745 if (skinframe && skinframe->base)
6748 skinframe->stain = NULL;
6749 skinframe->merged = NULL;
6750 skinframe->base = NULL;
6751 skinframe->pants = NULL;
6752 skinframe->shirt = NULL;
6753 skinframe->nmap = NULL;
6754 skinframe->gloss = NULL;
6755 skinframe->glow = NULL;
6756 skinframe->fog = NULL;
6757 skinframe->reflect = NULL;
6758 skinframe->hasalpha = false;
6760 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6764 if (developer_loading.integer)
6765 Con_Printf("loading quake skin \"%s\"\n", name);
6767 // 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)
6768 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height);
6769 memcpy(skinframe->qpixels, skindata, width*height);
6770 skinframe->qwidth = width;
6771 skinframe->qheight = height;
6774 for (i = 0;i < width * height;i++)
6775 featuresmask |= palette_featureflags[skindata[i]];
6777 skinframe->hasalpha = false;
6778 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6779 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6780 skinframe->qgeneratemerged = true;
6781 skinframe->qgeneratebase = skinframe->qhascolormapping;
6782 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6784 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6785 //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]);
6790 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6794 unsigned char *skindata;
6796 if (!skinframe->qpixels)
6799 if (!skinframe->qhascolormapping)
6800 colormapped = false;
6804 if (!skinframe->qgeneratebase)
6809 if (!skinframe->qgeneratemerged)
6813 width = skinframe->qwidth;
6814 height = skinframe->qheight;
6815 skindata = skinframe->qpixels;
6817 if (skinframe->qgeneratenmap)
6819 unsigned char *temp1, *temp2;
6820 skinframe->qgeneratenmap = false;
6821 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6822 temp2 = temp1 + width * height * 4;
6823 // use either a custom palette or the quake palette
6824 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6825 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6826 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);
6830 if (skinframe->qgenerateglow)
6832 skinframe->qgenerateglow = false;
6833 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6838 skinframe->qgeneratebase = false;
6839 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);
6840 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6841 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6845 skinframe->qgeneratemerged = false;
6846 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);
6849 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6851 Mem_Free(skinframe->qpixels);
6852 skinframe->qpixels = NULL;
6856 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)
6859 skinframe_t *skinframe;
6861 if (cls.state == ca_dedicated)
6864 // if already loaded just return it, otherwise make a new skinframe
6865 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6866 if (skinframe && skinframe->base)
6869 skinframe->stain = NULL;
6870 skinframe->merged = NULL;
6871 skinframe->base = NULL;
6872 skinframe->pants = NULL;
6873 skinframe->shirt = NULL;
6874 skinframe->nmap = NULL;
6875 skinframe->gloss = NULL;
6876 skinframe->glow = NULL;
6877 skinframe->fog = NULL;
6878 skinframe->reflect = NULL;
6879 skinframe->hasalpha = false;
6881 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6885 if (developer_loading.integer)
6886 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6888 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6889 if (textureflags & TEXF_ALPHA)
6891 for (i = 0;i < width * height;i++)
6893 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6895 skinframe->hasalpha = true;
6899 if (r_loadfog && skinframe->hasalpha)
6900 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6903 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6904 //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]);
6909 skinframe_t *R_SkinFrame_LoadMissing(void)
6911 skinframe_t *skinframe;
6913 if (cls.state == ca_dedicated)
6916 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6917 skinframe->stain = NULL;
6918 skinframe->merged = NULL;
6919 skinframe->base = NULL;
6920 skinframe->pants = NULL;
6921 skinframe->shirt = NULL;
6922 skinframe->nmap = NULL;
6923 skinframe->gloss = NULL;
6924 skinframe->glow = NULL;
6925 skinframe->fog = NULL;
6926 skinframe->reflect = NULL;
6927 skinframe->hasalpha = false;
6929 skinframe->avgcolor[0] = rand() / RAND_MAX;
6930 skinframe->avgcolor[1] = rand() / RAND_MAX;
6931 skinframe->avgcolor[2] = rand() / RAND_MAX;
6932 skinframe->avgcolor[3] = 1;
6937 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6938 typedef struct suffixinfo_s
6941 qboolean flipx, flipy, flipdiagonal;
6944 static suffixinfo_t suffix[3][6] =
6947 {"px", false, false, false},
6948 {"nx", false, false, false},
6949 {"py", false, false, false},
6950 {"ny", false, false, false},
6951 {"pz", false, false, false},
6952 {"nz", false, false, false}
6955 {"posx", false, false, false},
6956 {"negx", false, false, false},
6957 {"posy", false, false, false},
6958 {"negy", false, false, false},
6959 {"posz", false, false, false},
6960 {"negz", false, false, false}
6963 {"rt", true, false, true},
6964 {"lf", false, true, true},
6965 {"ft", true, true, false},
6966 {"bk", false, false, false},
6967 {"up", true, false, true},
6968 {"dn", true, false, true}
6972 static int componentorder[4] = {0, 1, 2, 3};
6974 rtexture_t *R_LoadCubemap(const char *basename)
6976 int i, j, cubemapsize;
6977 unsigned char *cubemappixels, *image_buffer;
6978 rtexture_t *cubemaptexture;
6980 // must start 0 so the first loadimagepixels has no requested width/height
6982 cubemappixels = NULL;
6983 cubemaptexture = NULL;
6984 // keep trying different suffix groups (posx, px, rt) until one loads
6985 for (j = 0;j < 3 && !cubemappixels;j++)
6987 // load the 6 images in the suffix group
6988 for (i = 0;i < 6;i++)
6990 // generate an image name based on the base and and suffix
6991 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6993 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
6995 // an image loaded, make sure width and height are equal
6996 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6998 // if this is the first image to load successfully, allocate the cubemap memory
6999 if (!cubemappixels && image_width >= 1)
7001 cubemapsize = image_width;
7002 // note this clears to black, so unavailable sides are black
7003 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
7005 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
7007 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);
7010 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
7012 Mem_Free(image_buffer);
7016 // if a cubemap loaded, upload it
7019 if (developer_loading.integer)
7020 Con_Printf("loading cubemap \"%s\"\n", basename);
7022 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
7023 Mem_Free(cubemappixels);
7027 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
7028 if (developer_loading.integer)
7030 Con_Printf("(tried tried images ");
7031 for (j = 0;j < 3;j++)
7032 for (i = 0;i < 6;i++)
7033 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
7034 Con_Print(" and was unable to find any of them).\n");
7037 return cubemaptexture;
7040 rtexture_t *R_GetCubemap(const char *basename)
7043 for (i = 0;i < r_texture_numcubemaps;i++)
7044 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
7045 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
7046 if (i >= MAX_CUBEMAPS)
7047 return r_texture_whitecube;
7048 r_texture_numcubemaps++;
7049 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
7050 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
7051 return r_texture_cubemaps[i].texture;
7054 void R_FreeCubemaps(void)
7057 for (i = 0;i < r_texture_numcubemaps;i++)
7059 if (developer_loading.integer)
7060 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
7061 if (r_texture_cubemaps[i].texture)
7062 R_FreeTexture(r_texture_cubemaps[i].texture);
7064 r_texture_numcubemaps = 0;
7067 void R_Main_FreeViewCache(void)
7069 if (r_refdef.viewcache.entityvisible)
7070 Mem_Free(r_refdef.viewcache.entityvisible);
7071 if (r_refdef.viewcache.world_pvsbits)
7072 Mem_Free(r_refdef.viewcache.world_pvsbits);
7073 if (r_refdef.viewcache.world_leafvisible)
7074 Mem_Free(r_refdef.viewcache.world_leafvisible);
7075 if (r_refdef.viewcache.world_surfacevisible)
7076 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7077 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
7080 void R_Main_ResizeViewCache(void)
7082 int numentities = r_refdef.scene.numentities;
7083 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
7084 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
7085 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
7086 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
7087 if (r_refdef.viewcache.maxentities < numentities)
7089 r_refdef.viewcache.maxentities = numentities;
7090 if (r_refdef.viewcache.entityvisible)
7091 Mem_Free(r_refdef.viewcache.entityvisible);
7092 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
7094 if (r_refdef.viewcache.world_numclusters != numclusters)
7096 r_refdef.viewcache.world_numclusters = numclusters;
7097 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
7098 if (r_refdef.viewcache.world_pvsbits)
7099 Mem_Free(r_refdef.viewcache.world_pvsbits);
7100 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
7102 if (r_refdef.viewcache.world_numleafs != numleafs)
7104 r_refdef.viewcache.world_numleafs = numleafs;
7105 if (r_refdef.viewcache.world_leafvisible)
7106 Mem_Free(r_refdef.viewcache.world_leafvisible);
7107 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
7109 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
7111 r_refdef.viewcache.world_numsurfaces = numsurfaces;
7112 if (r_refdef.viewcache.world_surfacevisible)
7113 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7114 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
7118 extern rtexture_t *loadingscreentexture;
7119 void gl_main_start(void)
7121 loadingscreentexture = NULL;
7122 r_texture_blanknormalmap = NULL;
7123 r_texture_white = NULL;
7124 r_texture_grey128 = NULL;
7125 r_texture_black = NULL;
7126 r_texture_whitecube = NULL;
7127 r_texture_normalizationcube = NULL;
7128 r_texture_fogattenuation = NULL;
7129 r_texture_fogheighttexture = NULL;
7130 r_texture_gammaramps = NULL;
7131 r_texture_numcubemaps = 0;
7133 r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
7134 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
7136 switch(vid.renderpath)
7138 case RENDERPATH_GL20:
7139 case RENDERPATH_CGGL:
7140 case RENDERPATH_D3D9:
7141 case RENDERPATH_D3D10:
7142 case RENDERPATH_D3D11:
7143 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7144 Cvar_SetValueQuick(&gl_combine, 1);
7145 Cvar_SetValueQuick(&r_glsl, 1);
7146 r_loadnormalmap = true;
7150 case RENDERPATH_GL13:
7151 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7152 Cvar_SetValueQuick(&gl_combine, 1);
7153 Cvar_SetValueQuick(&r_glsl, 0);
7154 r_loadnormalmap = false;
7155 r_loadgloss = false;
7158 case RENDERPATH_GL11:
7159 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7160 Cvar_SetValueQuick(&gl_combine, 0);
7161 Cvar_SetValueQuick(&r_glsl, 0);
7162 r_loadnormalmap = false;
7163 r_loadgloss = false;
7169 R_FrameData_Reset();
7173 memset(r_queries, 0, sizeof(r_queries));
7175 r_qwskincache = NULL;
7176 r_qwskincache_size = 0;
7178 // set up r_skinframe loading system for textures
7179 memset(&r_skinframe, 0, sizeof(r_skinframe));
7180 r_skinframe.loadsequence = 1;
7181 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7183 r_main_texturepool = R_AllocTexturePool();
7184 R_BuildBlankTextures();
7186 if (vid.support.arb_texture_cube_map)
7189 R_BuildNormalizationCube();
7191 r_texture_fogattenuation = NULL;
7192 r_texture_fogheighttexture = NULL;
7193 r_texture_gammaramps = NULL;
7194 //r_texture_fogintensity = NULL;
7195 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7196 memset(&r_waterstate, 0, sizeof(r_waterstate));
7197 r_glsl_permutation = NULL;
7198 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7199 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7200 glslshaderstring = NULL;
7202 r_cg_permutation = NULL;
7203 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7204 Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7205 cgshaderstring = NULL;
7208 r_hlsl_permutation = NULL;
7209 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7210 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7211 hlslshaderstring = NULL;
7213 memset(&r_svbsp, 0, sizeof (r_svbsp));
7215 r_refdef.fogmasktable_density = 0;
7218 void gl_main_shutdown(void)
7221 R_FrameData_Reset();
7223 R_Main_FreeViewCache();
7225 switch(vid.renderpath)
7227 case RENDERPATH_GL11:
7228 case RENDERPATH_GL13:
7229 case RENDERPATH_GL20:
7230 case RENDERPATH_CGGL:
7232 qglDeleteQueriesARB(r_maxqueries, r_queries);
7234 case RENDERPATH_D3D9:
7235 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7237 case RENDERPATH_D3D10:
7238 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7240 case RENDERPATH_D3D11:
7241 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7247 memset(r_queries, 0, sizeof(r_queries));
7249 r_qwskincache = NULL;
7250 r_qwskincache_size = 0;
7252 // clear out the r_skinframe state
7253 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7254 memset(&r_skinframe, 0, sizeof(r_skinframe));
7257 Mem_Free(r_svbsp.nodes);
7258 memset(&r_svbsp, 0, sizeof (r_svbsp));
7259 R_FreeTexturePool(&r_main_texturepool);
7260 loadingscreentexture = NULL;
7261 r_texture_blanknormalmap = NULL;
7262 r_texture_white = NULL;
7263 r_texture_grey128 = NULL;
7264 r_texture_black = NULL;
7265 r_texture_whitecube = NULL;
7266 r_texture_normalizationcube = NULL;
7267 r_texture_fogattenuation = NULL;
7268 r_texture_fogheighttexture = NULL;
7269 r_texture_gammaramps = NULL;
7270 r_texture_numcubemaps = 0;
7271 //r_texture_fogintensity = NULL;
7272 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7273 memset(&r_waterstate, 0, sizeof(r_waterstate));
7277 extern void CL_ParseEntityLump(char *entitystring);
7278 void gl_main_newmap(void)
7280 // FIXME: move this code to client
7281 char *entities, entname[MAX_QPATH];
7283 Mem_Free(r_qwskincache);
7284 r_qwskincache = NULL;
7285 r_qwskincache_size = 0;
7288 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7289 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7291 CL_ParseEntityLump(entities);
7295 if (cl.worldmodel->brush.entities)
7296 CL_ParseEntityLump(cl.worldmodel->brush.entities);
7298 R_Main_FreeViewCache();
7300 R_FrameData_Reset();
7303 void GL_Main_Init(void)
7305 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7307 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7308 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7309 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7310 if (gamemode == GAME_NEHAHRA)
7312 Cvar_RegisterVariable (&gl_fogenable);
7313 Cvar_RegisterVariable (&gl_fogdensity);
7314 Cvar_RegisterVariable (&gl_fogred);
7315 Cvar_RegisterVariable (&gl_foggreen);
7316 Cvar_RegisterVariable (&gl_fogblue);
7317 Cvar_RegisterVariable (&gl_fogstart);
7318 Cvar_RegisterVariable (&gl_fogend);
7319 Cvar_RegisterVariable (&gl_skyclip);
7321 Cvar_RegisterVariable(&r_motionblur);
7322 Cvar_RegisterVariable(&r_motionblur_maxblur);
7323 Cvar_RegisterVariable(&r_motionblur_bmin);
7324 Cvar_RegisterVariable(&r_motionblur_vmin);
7325 Cvar_RegisterVariable(&r_motionblur_vmax);
7326 Cvar_RegisterVariable(&r_motionblur_vcoeff);
7327 Cvar_RegisterVariable(&r_motionblur_randomize);
7328 Cvar_RegisterVariable(&r_damageblur);
7329 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7330 Cvar_RegisterVariable(&r_equalize_entities_minambient);
7331 Cvar_RegisterVariable(&r_equalize_entities_by);
7332 Cvar_RegisterVariable(&r_equalize_entities_to);
7333 Cvar_RegisterVariable(&r_depthfirst);
7334 Cvar_RegisterVariable(&r_useinfinitefarclip);
7335 Cvar_RegisterVariable(&r_farclip_base);
7336 Cvar_RegisterVariable(&r_farclip_world);
7337 Cvar_RegisterVariable(&r_nearclip);
7338 Cvar_RegisterVariable(&r_showbboxes);
7339 Cvar_RegisterVariable(&r_showsurfaces);
7340 Cvar_RegisterVariable(&r_showtris);
7341 Cvar_RegisterVariable(&r_shownormals);
7342 Cvar_RegisterVariable(&r_showlighting);
7343 Cvar_RegisterVariable(&r_showshadowvolumes);
7344 Cvar_RegisterVariable(&r_showcollisionbrushes);
7345 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7346 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7347 Cvar_RegisterVariable(&r_showdisabledepthtest);
7348 Cvar_RegisterVariable(&r_drawportals);
7349 Cvar_RegisterVariable(&r_drawentities);
7350 Cvar_RegisterVariable(&r_draw2d);
7351 Cvar_RegisterVariable(&r_drawworld);
7352 Cvar_RegisterVariable(&r_cullentities_trace);
7353 Cvar_RegisterVariable(&r_cullentities_trace_samples);
7354 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7355 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7356 Cvar_RegisterVariable(&r_cullentities_trace_delay);
7357 Cvar_RegisterVariable(&r_drawviewmodel);
7358 Cvar_RegisterVariable(&r_drawexteriormodel);
7359 Cvar_RegisterVariable(&r_speeds);
7360 Cvar_RegisterVariable(&r_fullbrights);
7361 Cvar_RegisterVariable(&r_wateralpha);
7362 Cvar_RegisterVariable(&r_dynamic);
7363 Cvar_RegisterVariable(&r_fakelight);
7364 Cvar_RegisterVariable(&r_fakelight_intensity);
7365 Cvar_RegisterVariable(&r_fullbright);
7366 Cvar_RegisterVariable(&r_shadows);
7367 Cvar_RegisterVariable(&r_shadows_darken);
7368 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7369 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7370 Cvar_RegisterVariable(&r_shadows_throwdistance);
7371 Cvar_RegisterVariable(&r_shadows_throwdirection);
7372 Cvar_RegisterVariable(&r_shadows_focus);
7373 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7374 Cvar_RegisterVariable(&r_q1bsp_skymasking);
7375 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7376 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7377 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7378 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7379 Cvar_RegisterVariable(&r_fog_exp2);
7380 Cvar_RegisterVariable(&r_drawfog);
7381 Cvar_RegisterVariable(&r_transparentdepthmasking);
7382 Cvar_RegisterVariable(&r_texture_dds_load);
7383 Cvar_RegisterVariable(&r_texture_dds_save);
7384 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7385 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7386 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7387 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7388 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7389 Cvar_RegisterVariable(&r_textureunits);
7390 Cvar_RegisterVariable(&gl_combine);
7391 Cvar_RegisterVariable(&r_glsl);
7392 Cvar_RegisterVariable(&r_glsl_deluxemapping);
7393 Cvar_RegisterVariable(&r_glsl_offsetmapping);
7394 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7395 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7396 Cvar_RegisterVariable(&r_glsl_postprocess);
7397 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7398 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7399 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7400 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7401 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
7402 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
7403 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
7404 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
7406 Cvar_RegisterVariable(&r_water);
7407 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7408 Cvar_RegisterVariable(&r_water_clippingplanebias);
7409 Cvar_RegisterVariable(&r_water_refractdistort);
7410 Cvar_RegisterVariable(&r_water_reflectdistort);
7411 Cvar_RegisterVariable(&r_water_scissormode);
7412 Cvar_RegisterVariable(&r_lerpsprites);
7413 Cvar_RegisterVariable(&r_lerpmodels);
7414 Cvar_RegisterVariable(&r_lerplightstyles);
7415 Cvar_RegisterVariable(&r_waterscroll);
7416 Cvar_RegisterVariable(&r_bloom);
7417 Cvar_RegisterVariable(&r_bloom_colorscale);
7418 Cvar_RegisterVariable(&r_bloom_brighten);
7419 Cvar_RegisterVariable(&r_bloom_blur);
7420 Cvar_RegisterVariable(&r_bloom_resolution);
7421 Cvar_RegisterVariable(&r_bloom_colorexponent);
7422 Cvar_RegisterVariable(&r_bloom_colorsubtract);
7423 Cvar_RegisterVariable(&r_hdr);
7424 Cvar_RegisterVariable(&r_hdr_scenebrightness);
7425 Cvar_RegisterVariable(&r_hdr_glowintensity);
7426 Cvar_RegisterVariable(&r_hdr_range);
7427 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7428 Cvar_RegisterVariable(&developer_texturelogging);
7429 Cvar_RegisterVariable(&gl_lightmaps);
7430 Cvar_RegisterVariable(&r_test);
7431 Cvar_RegisterVariable(&r_glsl_saturation);
7432 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
7433 Cvar_RegisterVariable(&r_framedatasize);
7434 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7435 Cvar_SetValue("r_fullbrights", 0);
7436 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7438 Cvar_RegisterVariable(&r_track_sprites);
7439 Cvar_RegisterVariable(&r_track_sprites_flags);
7440 Cvar_RegisterVariable(&r_track_sprites_scalew);
7441 Cvar_RegisterVariable(&r_track_sprites_scaleh);
7442 Cvar_RegisterVariable(&r_overheadsprites_perspective);
7443 Cvar_RegisterVariable(&r_overheadsprites_pushback);
7446 extern void R_Textures_Init(void);
7447 extern void GL_Draw_Init(void);
7448 extern void GL_Main_Init(void);
7449 extern void R_Shadow_Init(void);
7450 extern void R_Sky_Init(void);
7451 extern void GL_Surf_Init(void);
7452 extern void R_Particles_Init(void);
7453 extern void R_Explosion_Init(void);
7454 extern void gl_backend_init(void);
7455 extern void Sbar_Init(void);
7456 extern void R_LightningBeams_Init(void);
7457 extern void Mod_RenderInit(void);
7458 extern void Font_Init(void);
7460 void Render_Init(void)
7473 R_LightningBeams_Init();
7482 extern char *ENGINE_EXTENSIONS;
7485 gl_renderer = (const char *)qglGetString(GL_RENDERER);
7486 gl_vendor = (const char *)qglGetString(GL_VENDOR);
7487 gl_version = (const char *)qglGetString(GL_VERSION);
7488 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7492 if (!gl_platformextensions)
7493 gl_platformextensions = "";
7495 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7496 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7497 Con_Printf("GL_VERSION: %s\n", gl_version);
7498 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7499 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7501 VID_CheckExtensions();
7503 // LordHavoc: report supported extensions
7504 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7506 // clear to black (loading plaque will be seen over this)
7507 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7510 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7514 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7516 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7519 p = r_refdef.view.frustum + i;
7524 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7528 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7532 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7536 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7540 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7544 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7548 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7552 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7560 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7564 for (i = 0;i < numplanes;i++)
7571 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7575 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7579 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7583 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7587 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7591 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7595 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7599 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7607 //==================================================================================
7609 // LordHavoc: this stores temporary data used within the same frame
7611 qboolean r_framedata_failed;
7612 static size_t r_framedata_size;
7613 static size_t r_framedata_current;
7614 static void *r_framedata_base;
7616 void R_FrameData_Reset(void)
7618 if (r_framedata_base)
7619 Mem_Free(r_framedata_base);
7620 r_framedata_base = NULL;
7621 r_framedata_size = 0;
7622 r_framedata_current = 0;
7623 r_framedata_failed = false;
7626 void R_FrameData_NewFrame(void)
7629 if (r_framedata_failed)
7630 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
7631 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7632 wantedsize = bound(65536, wantedsize, 128*1024*1024);
7633 if (r_framedata_size != wantedsize)
7635 r_framedata_size = wantedsize;
7636 if (r_framedata_base)
7637 Mem_Free(r_framedata_base);
7638 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
7640 r_framedata_current = 0;
7641 r_framedata_failed = false;
7644 void *R_FrameData_Alloc(size_t size)
7648 // align to 16 byte boundary
7649 size = (size + 15) & ~15;
7650 data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
7651 r_framedata_current += size;
7654 if (r_framedata_current > r_framedata_size)
7655 r_framedata_failed = true;
7657 // return NULL on everything after a failure
7658 if (r_framedata_failed)
7664 void *R_FrameData_Store(size_t size, void *data)
7666 void *d = R_FrameData_Alloc(size);
7668 memcpy(d, data, size);
7672 //==================================================================================
7674 // LordHavoc: animcache originally written by Echon, rewritten since then
7677 * Animation cache prevents re-generating mesh data for an animated model
7678 * multiple times in one frame for lighting, shadowing, reflections, etc.
7681 void R_AnimCache_Free(void)
7685 void R_AnimCache_ClearCache(void)
7688 entity_render_t *ent;
7690 for (i = 0;i < r_refdef.scene.numentities;i++)
7692 ent = r_refdef.scene.entities[i];
7693 ent->animcache_vertex3f = NULL;
7694 ent->animcache_normal3f = NULL;
7695 ent->animcache_svector3f = NULL;
7696 ent->animcache_tvector3f = NULL;
7697 ent->animcache_vertexposition = NULL;
7698 ent->animcache_vertexmesh = NULL;
7699 ent->animcache_vertexpositionbuffer = NULL;
7700 ent->animcache_vertexmeshbuffer = NULL;
7704 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7708 // identical memory layout, so no need to allocate...
7709 // this also provides the vertexposition structure to everything, e.g.
7710 // depth masked rendering currently uses it even if having separate
7712 // NOTE: get rid of this optimization if changing it to e.g. 4f
7713 ent->animcache_vertexposition = (r_vertexposition_t *)ent->animcache_vertex3f;
7716 // get rid of following uses of VERTEXPOSITION, change to the array:
7717 // R_DrawTextureSurfaceList_Sky if skyrendermasked
7718 // R_DrawSurface_TransparentCallback if r_transparentdepthmasking.integer
7719 // R_DrawTextureSurfaceList_DepthOnly
7720 // R_Q1BSP_DrawShadowMap
7722 switch(vid.renderpath)
7724 case RENDERPATH_GL20:
7725 case RENDERPATH_CGGL:
7726 // need the meshbuffers if !gl_mesh_separatearrays.integer
7727 if (gl_mesh_separatearrays.integer)
7730 case RENDERPATH_D3D9:
7731 case RENDERPATH_D3D10:
7732 case RENDERPATH_D3D11:
7733 // always need the meshbuffers
7735 case RENDERPATH_GL13:
7736 case RENDERPATH_GL11:
7737 // never need the meshbuffers
7741 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7742 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7744 if (!ent->animcache_vertexposition)
7745 ent->animcache_vertexposition = (r_vertexposition_t *)R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
7747 if (ent->animcache_vertexposition)
7750 for (i = 0;i < numvertices;i++)
7751 memcpy(ent->animcache_vertexposition[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7753 // TODO: upload vertex buffer?
7755 if (ent->animcache_vertexmesh)
7757 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7758 for (i = 0;i < numvertices;i++)
7759 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7760 if (ent->animcache_svector3f)
7761 for (i = 0;i < numvertices;i++)
7762 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7763 if (ent->animcache_tvector3f)
7764 for (i = 0;i < numvertices;i++)
7765 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7766 if (ent->animcache_normal3f)
7767 for (i = 0;i < numvertices;i++)
7768 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7769 // TODO: upload vertex buffer?
7773 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7775 dp_model_t *model = ent->model;
7777 // see if it's already cached this frame
7778 if (ent->animcache_vertex3f)
7780 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7781 if (wantnormals || wanttangents)
7783 if (ent->animcache_normal3f)
7784 wantnormals = false;
7785 if (ent->animcache_svector3f)
7786 wanttangents = false;
7787 if (wantnormals || wanttangents)
7789 numvertices = model->surfmesh.num_vertices;
7791 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7794 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7795 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7797 if (!r_framedata_failed)
7799 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7800 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7807 // see if this ent is worth caching
7808 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7810 // get some memory for this entity and generate mesh data
7811 numvertices = model->surfmesh.num_vertices;
7812 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7814 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7817 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7818 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7820 if (!r_framedata_failed)
7822 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7823 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7826 return !r_framedata_failed;
7829 void R_AnimCache_CacheVisibleEntities(void)
7832 qboolean wantnormals = true;
7833 qboolean wanttangents = !r_showsurfaces.integer;
7835 switch(vid.renderpath)
7837 case RENDERPATH_GL20:
7838 case RENDERPATH_CGGL:
7839 case RENDERPATH_D3D9:
7840 case RENDERPATH_D3D10:
7841 case RENDERPATH_D3D11:
7843 case RENDERPATH_GL13:
7844 case RENDERPATH_GL11:
7845 wanttangents = false;
7849 if (r_shownormals.integer)
7850 wanttangents = wantnormals = true;
7852 // TODO: thread this
7853 // NOTE: R_PrepareRTLights() also caches entities
7855 for (i = 0;i < r_refdef.scene.numentities;i++)
7856 if (r_refdef.viewcache.entityvisible[i])
7857 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7860 //==================================================================================
7862 static void R_View_UpdateEntityLighting (void)
7865 entity_render_t *ent;
7866 vec3_t tempdiffusenormal, avg;
7867 vec_t f, fa, fd, fdd;
7868 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7870 for (i = 0;i < r_refdef.scene.numentities;i++)
7872 ent = r_refdef.scene.entities[i];
7874 // skip unseen models
7875 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7879 if (ent->model && ent->model->brush.num_leafs)
7881 // TODO: use modellight for r_ambient settings on world?
7882 VectorSet(ent->modellight_ambient, 0, 0, 0);
7883 VectorSet(ent->modellight_diffuse, 0, 0, 0);
7884 VectorSet(ent->modellight_lightdir, 0, 0, 1);
7888 // fetch the lighting from the worldmodel data
7889 VectorClear(ent->modellight_ambient);
7890 VectorClear(ent->modellight_diffuse);
7891 VectorClear(tempdiffusenormal);
7892 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7895 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7897 // complete lightning for lit sprites
7898 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
7899 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
7901 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
7902 org[2] = org[2] + r_overheadsprites_pushback.value;
7903 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, ent->modellight_lightdir, org, true, true);
7906 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7908 if(ent->flags & RENDER_EQUALIZE)
7910 // first fix up ambient lighting...
7911 if(r_equalize_entities_minambient.value > 0)
7913 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7916 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7917 if(fa < r_equalize_entities_minambient.value * fd)
7920 // fa'/fd' = minambient
7921 // fa'+0.25*fd' = fa+0.25*fd
7923 // fa' = fd' * minambient
7924 // fd'*(0.25+minambient) = fa+0.25*fd
7926 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7927 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7929 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7930 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
7931 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7932 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7937 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7939 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
7940 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
7943 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
7944 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
7945 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7951 VectorSet(ent->modellight_ambient, 1, 1, 1);
7953 // move the light direction into modelspace coordinates for lighting code
7954 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7955 if(VectorLength2(ent->modellight_lightdir) == 0)
7956 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7957 VectorNormalize(ent->modellight_lightdir);
7961 #define MAX_LINEOFSIGHTTRACES 64
7963 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7966 vec3_t boxmins, boxmaxs;
7969 dp_model_t *model = r_refdef.scene.worldmodel;
7971 if (!model || !model->brush.TraceLineOfSight)
7974 // expand the box a little
7975 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7976 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7977 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7978 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7979 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7980 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7982 // return true if eye is inside enlarged box
7983 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7987 VectorCopy(eye, start);
7988 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7989 if (model->brush.TraceLineOfSight(model, start, end))
7992 // try various random positions
7993 for (i = 0;i < numsamples;i++)
7995 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7996 if (model->brush.TraceLineOfSight(model, start, end))
8004 static void R_View_UpdateEntityVisible (void)
8009 entity_render_t *ent;
8011 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8012 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8013 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
8014 : RENDER_EXTERIORMODEL;
8015 if (!r_drawviewmodel.integer)
8016 renderimask |= RENDER_VIEWMODEL;
8017 if (!r_drawexteriormodel.integer)
8018 renderimask |= RENDER_EXTERIORMODEL;
8019 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
8021 // worldmodel can check visibility
8022 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
8023 for (i = 0;i < r_refdef.scene.numentities;i++)
8025 ent = r_refdef.scene.entities[i];
8026 if (!(ent->flags & renderimask))
8027 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)))
8028 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))
8029 r_refdef.viewcache.entityvisible[i] = true;
8031 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
8032 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
8034 for (i = 0;i < r_refdef.scene.numentities;i++)
8036 ent = r_refdef.scene.entities[i];
8037 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
8039 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
8041 continue; // temp entities do pvs only
8042 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
8043 ent->last_trace_visibility = realtime;
8044 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
8045 r_refdef.viewcache.entityvisible[i] = 0;
8052 // no worldmodel or it can't check visibility
8053 for (i = 0;i < r_refdef.scene.numentities;i++)
8055 ent = r_refdef.scene.entities[i];
8056 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));
8061 /// only used if skyrendermasked, and normally returns false
8062 int R_DrawBrushModelsSky (void)
8065 entity_render_t *ent;
8068 for (i = 0;i < r_refdef.scene.numentities;i++)
8070 if (!r_refdef.viewcache.entityvisible[i])
8072 ent = r_refdef.scene.entities[i];
8073 if (!ent->model || !ent->model->DrawSky)
8075 ent->model->DrawSky(ent);
8081 static void R_DrawNoModel(entity_render_t *ent);
8082 static void R_DrawModels(void)
8085 entity_render_t *ent;
8087 for (i = 0;i < r_refdef.scene.numentities;i++)
8089 if (!r_refdef.viewcache.entityvisible[i])
8091 ent = r_refdef.scene.entities[i];
8092 r_refdef.stats.entities++;
8093 if (ent->model && ent->model->Draw != NULL)
8094 ent->model->Draw(ent);
8100 static void R_DrawModelsDepth(void)
8103 entity_render_t *ent;
8105 for (i = 0;i < r_refdef.scene.numentities;i++)
8107 if (!r_refdef.viewcache.entityvisible[i])
8109 ent = r_refdef.scene.entities[i];
8110 if (ent->model && ent->model->DrawDepth != NULL)
8111 ent->model->DrawDepth(ent);
8115 static void R_DrawModelsDebug(void)
8118 entity_render_t *ent;
8120 for (i = 0;i < r_refdef.scene.numentities;i++)
8122 if (!r_refdef.viewcache.entityvisible[i])
8124 ent = r_refdef.scene.entities[i];
8125 if (ent->model && ent->model->DrawDebug != NULL)
8126 ent->model->DrawDebug(ent);
8130 static void R_DrawModelsAddWaterPlanes(void)
8133 entity_render_t *ent;
8135 for (i = 0;i < r_refdef.scene.numentities;i++)
8137 if (!r_refdef.viewcache.entityvisible[i])
8139 ent = r_refdef.scene.entities[i];
8140 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
8141 ent->model->DrawAddWaterPlanes(ent);
8145 static void R_View_SetFrustum(const int *scissor)
8148 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
8149 vec3_t forward, left, up, origin, v;
8153 // flipped x coordinates (because x points left here)
8154 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8155 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8157 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
8158 switch(vid.renderpath)
8160 case RENDERPATH_D3D9:
8161 case RENDERPATH_D3D10:
8162 case RENDERPATH_D3D11:
8163 // non-flipped y coordinates
8164 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8165 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8167 case RENDERPATH_GL11:
8168 case RENDERPATH_GL13:
8169 case RENDERPATH_GL20:
8170 case RENDERPATH_CGGL:
8171 // non-flipped y coordinates
8172 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8173 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8178 // we can't trust r_refdef.view.forward and friends in reflected scenes
8179 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
8182 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
8183 r_refdef.view.frustum[0].normal[1] = 0 - 0;
8184 r_refdef.view.frustum[0].normal[2] = -1 - 0;
8185 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
8186 r_refdef.view.frustum[1].normal[1] = 0 + 0;
8187 r_refdef.view.frustum[1].normal[2] = -1 + 0;
8188 r_refdef.view.frustum[2].normal[0] = 0 - 0;
8189 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
8190 r_refdef.view.frustum[2].normal[2] = -1 - 0;
8191 r_refdef.view.frustum[3].normal[0] = 0 + 0;
8192 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
8193 r_refdef.view.frustum[3].normal[2] = -1 + 0;
8197 zNear = r_refdef.nearclip;
8198 nudge = 1.0 - 1.0 / (1<<23);
8199 r_refdef.view.frustum[4].normal[0] = 0 - 0;
8200 r_refdef.view.frustum[4].normal[1] = 0 - 0;
8201 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
8202 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
8203 r_refdef.view.frustum[5].normal[0] = 0 + 0;
8204 r_refdef.view.frustum[5].normal[1] = 0 + 0;
8205 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
8206 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
8212 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8213 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8214 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8215 r_refdef.view.frustum[0].dist = m[15] - m[12];
8217 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8218 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8219 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8220 r_refdef.view.frustum[1].dist = m[15] + m[12];
8222 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8223 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8224 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8225 r_refdef.view.frustum[2].dist = m[15] - m[13];
8227 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8228 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8229 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8230 r_refdef.view.frustum[3].dist = m[15] + m[13];
8232 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8233 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8234 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8235 r_refdef.view.frustum[4].dist = m[15] - m[14];
8237 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8238 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8239 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8240 r_refdef.view.frustum[5].dist = m[15] + m[14];
8243 if (r_refdef.view.useperspective)
8245 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8246 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]);
8247 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]);
8248 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]);
8249 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]);
8251 // then the normals from the corners relative to origin
8252 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
8253 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
8254 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
8255 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
8257 // in a NORMAL view, forward cross left == up
8258 // in a REFLECTED view, forward cross left == down
8259 // so our cross products above need to be adjusted for a left handed coordinate system
8260 CrossProduct(forward, left, v);
8261 if(DotProduct(v, up) < 0)
8263 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
8264 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
8265 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
8266 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
8269 // Leaving those out was a mistake, those were in the old code, and they
8270 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8271 // I couldn't reproduce it after adding those normalizations. --blub
8272 VectorNormalize(r_refdef.view.frustum[0].normal);
8273 VectorNormalize(r_refdef.view.frustum[1].normal);
8274 VectorNormalize(r_refdef.view.frustum[2].normal);
8275 VectorNormalize(r_refdef.view.frustum[3].normal);
8277 // make the corners absolute
8278 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
8279 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
8280 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
8281 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
8284 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8286 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8287 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8288 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8289 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8290 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8294 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8295 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8296 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8297 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8298 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8299 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8300 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8301 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8302 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8303 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8305 r_refdef.view.numfrustumplanes = 5;
8307 if (r_refdef.view.useclipplane)
8309 r_refdef.view.numfrustumplanes = 6;
8310 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8313 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8314 PlaneClassify(r_refdef.view.frustum + i);
8316 // LordHavoc: note to all quake engine coders, Quake had a special case
8317 // for 90 degrees which assumed a square view (wrong), so I removed it,
8318 // Quake2 has it disabled as well.
8320 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8321 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8322 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8323 //PlaneClassify(&frustum[0]);
8325 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8326 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8327 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8328 //PlaneClassify(&frustum[1]);
8330 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8331 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8332 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8333 //PlaneClassify(&frustum[2]);
8335 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8336 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8337 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8338 //PlaneClassify(&frustum[3]);
8341 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8342 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8343 //PlaneClassify(&frustum[4]);
8346 void R_View_UpdateWithScissor(const int *myscissor)
8348 R_Main_ResizeViewCache();
8349 R_View_SetFrustum(myscissor);
8350 R_View_WorldVisibility(r_refdef.view.useclipplane);
8351 R_View_UpdateEntityVisible();
8352 R_View_UpdateEntityLighting();
8355 void R_View_Update(void)
8357 R_Main_ResizeViewCache();
8358 R_View_SetFrustum(NULL);
8359 R_View_WorldVisibility(r_refdef.view.useclipplane);
8360 R_View_UpdateEntityVisible();
8361 R_View_UpdateEntityLighting();
8364 void R_SetupView(qboolean allowwaterclippingplane)
8366 const float *customclipplane = NULL;
8368 if (r_refdef.view.useclipplane && allowwaterclippingplane)
8370 // LordHavoc: couldn't figure out how to make this approach the
8371 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8372 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8373 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8374 dist = r_refdef.view.clipplane.dist;
8375 plane[0] = r_refdef.view.clipplane.normal[0];
8376 plane[1] = r_refdef.view.clipplane.normal[1];
8377 plane[2] = r_refdef.view.clipplane.normal[2];
8379 customclipplane = plane;
8382 if (!r_refdef.view.useperspective)
8383 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);
8384 else if (vid.stencil && r_useinfinitefarclip.integer)
8385 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);
8387 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);
8388 R_SetViewport(&r_refdef.view.viewport);
8391 void R_EntityMatrix(const matrix4x4_t *matrix)
8393 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8395 gl_modelmatrixchanged = false;
8396 gl_modelmatrix = *matrix;
8397 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8398 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8399 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8400 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8402 switch(vid.renderpath)
8404 case RENDERPATH_D3D9:
8406 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8407 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8410 case RENDERPATH_D3D10:
8411 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8413 case RENDERPATH_D3D11:
8414 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8416 case RENDERPATH_GL20:
8417 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8418 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8419 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8421 case RENDERPATH_CGGL:
8424 if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8425 if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8426 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8429 case RENDERPATH_GL13:
8430 case RENDERPATH_GL11:
8431 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8437 void R_ResetViewRendering2D(void)
8439 r_viewport_t viewport;
8442 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8443 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);
8444 R_SetViewport(&viewport);
8445 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8446 GL_Color(1, 1, 1, 1);
8447 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8448 GL_BlendFunc(GL_ONE, GL_ZERO);
8449 GL_AlphaTest(false);
8450 GL_ScissorTest(false);
8451 GL_DepthMask(false);
8452 GL_DepthRange(0, 1);
8453 GL_DepthTest(false);
8454 GL_DepthFunc(GL_LEQUAL);
8455 R_EntityMatrix(&identitymatrix);
8456 R_Mesh_ResetTextureState();
8457 GL_PolygonOffset(0, 0);
8458 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8459 switch(vid.renderpath)
8461 case RENDERPATH_GL11:
8462 case RENDERPATH_GL13:
8463 case RENDERPATH_GL20:
8464 case RENDERPATH_CGGL:
8465 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8467 case RENDERPATH_D3D9:
8468 case RENDERPATH_D3D10:
8469 case RENDERPATH_D3D11:
8472 GL_CullFace(GL_NONE);
8475 void R_ResetViewRendering3D(void)
8480 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8481 GL_Color(1, 1, 1, 1);
8482 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8483 GL_BlendFunc(GL_ONE, GL_ZERO);
8484 GL_AlphaTest(false);
8485 GL_ScissorTest(true);
8487 GL_DepthRange(0, 1);
8489 GL_DepthFunc(GL_LEQUAL);
8490 R_EntityMatrix(&identitymatrix);
8491 R_Mesh_ResetTextureState();
8492 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8493 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8494 switch(vid.renderpath)
8496 case RENDERPATH_GL11:
8497 case RENDERPATH_GL13:
8498 case RENDERPATH_GL20:
8499 case RENDERPATH_CGGL:
8500 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8502 case RENDERPATH_D3D9:
8503 case RENDERPATH_D3D10:
8504 case RENDERPATH_D3D11:
8507 GL_CullFace(r_refdef.view.cullface_back);
8512 R_RenderView_UpdateViewVectors
8515 static void R_RenderView_UpdateViewVectors(void)
8517 // break apart the view matrix into vectors for various purposes
8518 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8519 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8520 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8521 VectorNegate(r_refdef.view.left, r_refdef.view.right);
8522 // make an inverted copy of the view matrix for tracking sprites
8523 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8526 void R_RenderScene(void);
8527 void R_RenderWaterPlanes(void);
8529 static void R_Water_StartFrame(void)
8532 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8533 r_waterstate_waterplane_t *p;
8535 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8538 switch(vid.renderpath)
8540 case RENDERPATH_GL20:
8541 case RENDERPATH_CGGL:
8542 case RENDERPATH_D3D9:
8543 case RENDERPATH_D3D10:
8544 case RENDERPATH_D3D11:
8546 case RENDERPATH_GL13:
8547 case RENDERPATH_GL11:
8551 // set waterwidth and waterheight to the water resolution that will be
8552 // used (often less than the screen resolution for faster rendering)
8553 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8554 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8556 // calculate desired texture sizes
8557 // can't use water if the card does not support the texture size
8558 if (!r_water.integer || r_showsurfaces.integer)
8559 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8560 else if (vid.support.arb_texture_non_power_of_two)
8562 texturewidth = waterwidth;
8563 textureheight = waterheight;
8564 camerawidth = waterwidth;
8565 cameraheight = waterheight;
8569 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
8570 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
8571 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
8572 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
8575 // allocate textures as needed
8576 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8578 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8579 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8581 if (p->texture_refraction)
8582 R_FreeTexture(p->texture_refraction);
8583 p->texture_refraction = NULL;
8584 if (p->texture_reflection)
8585 R_FreeTexture(p->texture_reflection);
8586 p->texture_reflection = NULL;
8587 if (p->texture_camera)
8588 R_FreeTexture(p->texture_camera);
8589 p->texture_camera = NULL;
8591 memset(&r_waterstate, 0, sizeof(r_waterstate));
8592 r_waterstate.texturewidth = texturewidth;
8593 r_waterstate.textureheight = textureheight;
8594 r_waterstate.camerawidth = camerawidth;
8595 r_waterstate.cameraheight = cameraheight;
8598 if (r_waterstate.texturewidth)
8600 r_waterstate.enabled = true;
8602 // when doing a reduced render (HDR) we want to use a smaller area
8603 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8604 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8606 // set up variables that will be used in shader setup
8607 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8608 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8609 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8610 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8613 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8614 r_waterstate.numwaterplanes = 0;
8617 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8619 int triangleindex, planeindex;
8625 r_waterstate_waterplane_t *p;
8626 texture_t *t = R_GetCurrentTexture(surface->texture);
8628 // just use the first triangle with a valid normal for any decisions
8629 VectorClear(normal);
8630 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8632 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8633 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8634 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8635 TriangleNormal(vert[0], vert[1], vert[2], normal);
8636 if (VectorLength2(normal) >= 0.001)
8640 VectorCopy(normal, plane.normal);
8641 VectorNormalize(plane.normal);
8642 plane.dist = DotProduct(vert[0], plane.normal);
8643 PlaneClassify(&plane);
8644 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8646 // skip backfaces (except if nocullface is set)
8647 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8649 VectorNegate(plane.normal, plane.normal);
8651 PlaneClassify(&plane);
8655 // find a matching plane if there is one
8656 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8657 if(p->camera_entity == t->camera_entity)
8658 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8660 if (planeindex >= r_waterstate.maxwaterplanes)
8661 return; // nothing we can do, out of planes
8663 // if this triangle does not fit any known plane rendered this frame, add one
8664 if (planeindex >= r_waterstate.numwaterplanes)
8666 // store the new plane
8667 r_waterstate.numwaterplanes++;
8669 // clear materialflags and pvs
8670 p->materialflags = 0;
8671 p->pvsvalid = false;
8672 p->camera_entity = t->camera_entity;
8673 VectorCopy(surface->mins, p->mins);
8674 VectorCopy(surface->maxs, p->maxs);
8679 p->mins[0] = min(p->mins[0], surface->mins[0]);
8680 p->mins[1] = min(p->mins[1], surface->mins[1]);
8681 p->mins[2] = min(p->mins[2], surface->mins[2]);
8682 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8683 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8684 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8686 // merge this surface's materialflags into the waterplane
8687 p->materialflags |= t->currentmaterialflags;
8688 if(!(p->materialflags & MATERIALFLAG_CAMERA))
8690 // merge this surface's PVS into the waterplane
8691 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8692 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8693 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8695 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8701 static void R_Water_ProcessPlanes(void)
8704 r_refdef_view_t originalview;
8705 r_refdef_view_t myview;
8707 r_waterstate_waterplane_t *p;
8710 originalview = r_refdef.view;
8712 // make sure enough textures are allocated
8713 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8715 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8717 if (!p->texture_refraction)
8718 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);
8719 if (!p->texture_refraction)
8722 else if (p->materialflags & MATERIALFLAG_CAMERA)
8724 if (!p->texture_camera)
8725 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);
8726 if (!p->texture_camera)
8730 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8732 if (!p->texture_reflection)
8733 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);
8734 if (!p->texture_reflection)
8740 r_refdef.view = originalview;
8741 r_refdef.view.showdebug = false;
8742 r_refdef.view.width = r_waterstate.waterwidth;
8743 r_refdef.view.height = r_waterstate.waterheight;
8744 r_refdef.view.useclipplane = true;
8745 myview = r_refdef.view;
8746 r_waterstate.renderingscene = true;
8747 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8749 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8751 r_refdef.view = myview;
8752 if(r_water_scissormode.integer)
8755 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8756 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8759 // render reflected scene and copy into texture
8760 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8761 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8762 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8763 r_refdef.view.clipplane = p->plane;
8765 // reverse the cullface settings for this render
8766 r_refdef.view.cullface_front = GL_FRONT;
8767 r_refdef.view.cullface_back = GL_BACK;
8768 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8770 r_refdef.view.usecustompvs = true;
8772 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8774 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8777 R_ResetViewRendering3D();
8778 R_ClearScreen(r_refdef.fogenabled);
8779 if(r_water_scissormode.integer & 2)
8780 R_View_UpdateWithScissor(myscissor);
8783 if(r_water_scissormode.integer & 1)
8784 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8787 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);
8790 // render the normal view scene and copy into texture
8791 // (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)
8792 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8794 r_refdef.view = myview;
8795 if(r_water_scissormode.integer)
8798 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8799 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8802 r_waterstate.renderingrefraction = true;
8804 r_refdef.view.clipplane = p->plane;
8805 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8806 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8808 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8810 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8811 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8812 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8813 R_RenderView_UpdateViewVectors();
8814 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8816 r_refdef.view.usecustompvs = true;
8817 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);
8821 PlaneClassify(&r_refdef.view.clipplane);
8823 R_ResetViewRendering3D();
8824 R_ClearScreen(r_refdef.fogenabled);
8825 if(r_water_scissormode.integer & 2)
8826 R_View_UpdateWithScissor(myscissor);
8829 if(r_water_scissormode.integer & 1)
8830 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8833 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);
8834 r_waterstate.renderingrefraction = false;
8836 else if (p->materialflags & MATERIALFLAG_CAMERA)
8838 r_refdef.view = myview;
8840 r_refdef.view.clipplane = p->plane;
8841 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8842 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8844 r_refdef.view.width = r_waterstate.camerawidth;
8845 r_refdef.view.height = r_waterstate.cameraheight;
8846 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8847 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8849 if(p->camera_entity)
8851 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8852 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8855 // note: all of the view is used for displaying... so
8856 // there is no use in scissoring
8858 // reverse the cullface settings for this render
8859 r_refdef.view.cullface_front = GL_FRONT;
8860 r_refdef.view.cullface_back = GL_BACK;
8861 // also reverse the view matrix
8862 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
8863 R_RenderView_UpdateViewVectors();
8864 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8866 r_refdef.view.usecustompvs = true;
8867 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);
8870 // camera needs no clipplane
8871 r_refdef.view.useclipplane = false;
8873 PlaneClassify(&r_refdef.view.clipplane);
8875 R_ResetViewRendering3D();
8876 R_ClearScreen(r_refdef.fogenabled);
8880 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);
8881 r_waterstate.renderingrefraction = false;
8885 r_waterstate.renderingscene = false;
8886 r_refdef.view = originalview;
8887 R_ResetViewRendering3D();
8888 R_ClearScreen(r_refdef.fogenabled);
8892 r_refdef.view = originalview;
8893 r_waterstate.renderingscene = false;
8894 Cvar_SetValueQuick(&r_water, 0);
8895 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
8899 void R_Bloom_StartFrame(void)
8901 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8903 switch(vid.renderpath)
8905 case RENDERPATH_GL20:
8906 case RENDERPATH_CGGL:
8907 case RENDERPATH_D3D9:
8908 case RENDERPATH_D3D10:
8909 case RENDERPATH_D3D11:
8911 case RENDERPATH_GL13:
8912 case RENDERPATH_GL11:
8916 // set bloomwidth and bloomheight to the bloom resolution that will be
8917 // used (often less than the screen resolution for faster rendering)
8918 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8919 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8920 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8921 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8922 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8924 // calculate desired texture sizes
8925 if (vid.support.arb_texture_non_power_of_two)
8927 screentexturewidth = r_refdef.view.width;
8928 screentextureheight = r_refdef.view.height;
8929 bloomtexturewidth = r_bloomstate.bloomwidth;
8930 bloomtextureheight = r_bloomstate.bloomheight;
8934 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
8935 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
8936 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
8937 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
8940 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))
8942 Cvar_SetValueQuick(&r_hdr, 0);
8943 Cvar_SetValueQuick(&r_bloom, 0);
8944 Cvar_SetValueQuick(&r_motionblur, 0);
8945 Cvar_SetValueQuick(&r_damageblur, 0);
8948 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)))
8949 screentexturewidth = screentextureheight = 0;
8950 if (!r_hdr.integer && !r_bloom.integer)
8951 bloomtexturewidth = bloomtextureheight = 0;
8953 // allocate textures as needed
8954 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8956 if (r_bloomstate.texture_screen)
8957 R_FreeTexture(r_bloomstate.texture_screen);
8958 r_bloomstate.texture_screen = NULL;
8959 r_bloomstate.screentexturewidth = screentexturewidth;
8960 r_bloomstate.screentextureheight = screentextureheight;
8961 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8962 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);
8964 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8966 if (r_bloomstate.texture_bloom)
8967 R_FreeTexture(r_bloomstate.texture_bloom);
8968 r_bloomstate.texture_bloom = NULL;
8969 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8970 r_bloomstate.bloomtextureheight = bloomtextureheight;
8971 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8972 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);
8975 // when doing a reduced render (HDR) we want to use a smaller area
8976 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8977 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8978 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8979 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8980 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8982 // set up a texcoord array for the full resolution screen image
8983 // (we have to keep this around to copy back during final render)
8984 r_bloomstate.screentexcoord2f[0] = 0;
8985 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
8986 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
8987 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
8988 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
8989 r_bloomstate.screentexcoord2f[5] = 0;
8990 r_bloomstate.screentexcoord2f[6] = 0;
8991 r_bloomstate.screentexcoord2f[7] = 0;
8993 // set up a texcoord array for the reduced resolution bloom image
8994 // (which will be additive blended over the screen image)
8995 r_bloomstate.bloomtexcoord2f[0] = 0;
8996 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8997 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8998 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8999 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9000 r_bloomstate.bloomtexcoord2f[5] = 0;
9001 r_bloomstate.bloomtexcoord2f[6] = 0;
9002 r_bloomstate.bloomtexcoord2f[7] = 0;
9004 switch(vid.renderpath)
9006 case RENDERPATH_GL11:
9007 case RENDERPATH_GL13:
9008 case RENDERPATH_GL20:
9009 case RENDERPATH_CGGL:
9011 case RENDERPATH_D3D9:
9012 case RENDERPATH_D3D10:
9013 case RENDERPATH_D3D11:
9016 for (i = 0;i < 4;i++)
9018 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
9019 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
9020 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
9021 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
9027 if (r_hdr.integer || r_bloom.integer)
9029 r_bloomstate.enabled = true;
9030 r_bloomstate.hdr = r_hdr.integer != 0;
9033 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);
9036 void R_Bloom_CopyBloomTexture(float colorscale)
9038 r_refdef.stats.bloom++;
9040 // scale down screen texture to the bloom texture size
9042 R_SetViewport(&r_bloomstate.viewport);
9043 GL_BlendFunc(GL_ONE, GL_ZERO);
9044 GL_Color(colorscale, colorscale, colorscale, 1);
9045 // 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...
9046 switch(vid.renderpath)
9048 case RENDERPATH_GL11:
9049 case RENDERPATH_GL13:
9050 case RENDERPATH_GL20:
9051 case RENDERPATH_CGGL:
9052 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9054 case RENDERPATH_D3D9:
9055 case RENDERPATH_D3D10:
9056 case RENDERPATH_D3D11:
9057 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9060 // TODO: do boxfilter scale-down in shader?
9061 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9062 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9063 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9065 // we now have a bloom image in the framebuffer
9066 // copy it into the bloom image texture for later processing
9067 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);
9068 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9071 void R_Bloom_CopyHDRTexture(void)
9073 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);
9074 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9077 void R_Bloom_MakeTexture(void)
9080 float xoffset, yoffset, r, brighten;
9082 r_refdef.stats.bloom++;
9084 R_ResetViewRendering2D();
9086 // we have a bloom image in the framebuffer
9088 R_SetViewport(&r_bloomstate.viewport);
9090 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
9093 r = bound(0, r_bloom_colorexponent.value / x, 1);
9094 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9096 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
9097 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9098 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9099 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9101 // copy the vertically blurred bloom view to a texture
9102 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);
9103 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9106 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
9107 brighten = r_bloom_brighten.value;
9109 brighten *= r_hdr_range.value;
9110 brighten = sqrt(brighten);
9112 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
9113 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9115 for (dir = 0;dir < 2;dir++)
9117 // blend on at multiple vertical offsets to achieve a vertical blur
9118 // TODO: do offset blends using GLSL
9119 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
9120 GL_BlendFunc(GL_ONE, GL_ZERO);
9121 for (x = -range;x <= range;x++)
9123 if (!dir){xoffset = 0;yoffset = x;}
9124 else {xoffset = x;yoffset = 0;}
9125 xoffset /= (float)r_bloomstate.bloomtexturewidth;
9126 yoffset /= (float)r_bloomstate.bloomtextureheight;
9127 // compute a texcoord array with the specified x and y offset
9128 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
9129 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9130 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9131 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9132 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9133 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
9134 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
9135 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
9136 // this r value looks like a 'dot' particle, fading sharply to
9137 // black at the edges
9138 // (probably not realistic but looks good enough)
9139 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
9140 //r = brighten/(range*2+1);
9141 r = brighten / (range * 2 + 1);
9143 r *= (1 - x*x/(float)(range*range));
9144 GL_Color(r, r, r, 1);
9145 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
9146 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9147 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9148 GL_BlendFunc(GL_ONE, GL_ONE);
9151 // copy the vertically blurred bloom view to a texture
9152 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);
9153 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9157 void R_HDR_RenderBloomTexture(void)
9159 int oldwidth, oldheight;
9160 float oldcolorscale;
9162 oldcolorscale = r_refdef.view.colorscale;
9163 oldwidth = r_refdef.view.width;
9164 oldheight = r_refdef.view.height;
9165 r_refdef.view.width = r_bloomstate.bloomwidth;
9166 r_refdef.view.height = r_bloomstate.bloomheight;
9168 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
9169 // TODO: add exposure compensation features
9170 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
9172 r_refdef.view.showdebug = false;
9173 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
9175 R_ResetViewRendering3D();
9177 R_ClearScreen(r_refdef.fogenabled);
9178 if (r_timereport_active)
9179 R_TimeReport("HDRclear");
9182 if (r_timereport_active)
9183 R_TimeReport("visibility");
9185 // only do secondary renders with HDR if r_hdr is 2 or higher
9186 r_waterstate.numwaterplanes = 0;
9187 if (r_waterstate.enabled && r_hdr.integer >= 2)
9188 R_RenderWaterPlanes();
9190 r_refdef.view.showdebug = true;
9192 r_waterstate.numwaterplanes = 0;
9194 R_ResetViewRendering2D();
9196 R_Bloom_CopyHDRTexture();
9197 R_Bloom_MakeTexture();
9199 // restore the view settings
9200 r_refdef.view.width = oldwidth;
9201 r_refdef.view.height = oldheight;
9202 r_refdef.view.colorscale = oldcolorscale;
9204 R_ResetViewRendering3D();
9206 R_ClearScreen(r_refdef.fogenabled);
9207 if (r_timereport_active)
9208 R_TimeReport("viewclear");
9211 static void R_BlendView(void)
9213 unsigned int permutation;
9214 float uservecs[4][4];
9216 switch (vid.renderpath)
9218 case RENDERPATH_GL20:
9219 case RENDERPATH_CGGL:
9220 case RENDERPATH_D3D9:
9221 case RENDERPATH_D3D10:
9222 case RENDERPATH_D3D11:
9224 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
9225 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
9226 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
9227 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
9228 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
9230 if (r_bloomstate.texture_screen)
9232 // make sure the buffer is available
9233 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
9235 R_ResetViewRendering2D();
9237 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
9239 // declare variables
9241 static float avgspeed;
9243 speed = VectorLength(cl.movement_velocity);
9245 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
9246 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
9248 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
9249 speed = bound(0, speed, 1);
9250 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
9252 // calculate values into a standard alpha
9253 cl.motionbluralpha = 1 - exp(-
9255 (r_motionblur.value * speed / 80)
9257 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
9260 max(0.0001, cl.time - cl.oldtime) // fps independent
9263 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
9264 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
9266 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
9268 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9269 GL_Color(1, 1, 1, cl.motionbluralpha);
9270 switch(vid.renderpath)
9272 case RENDERPATH_GL11:
9273 case RENDERPATH_GL13:
9274 case RENDERPATH_GL20:
9275 case RENDERPATH_CGGL:
9276 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9278 case RENDERPATH_D3D9:
9279 case RENDERPATH_D3D10:
9280 case RENDERPATH_D3D11:
9281 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9284 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9285 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9286 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9290 // copy view into the screen texture
9291 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);
9292 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9294 else if (!r_bloomstate.texture_bloom)
9296 // we may still have to do view tint...
9297 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9299 // apply a color tint to the whole view
9300 R_ResetViewRendering2D();
9301 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9302 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9303 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9304 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9305 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9307 break; // no screen processing, no bloom, skip it
9310 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9312 // render simple bloom effect
9313 // copy the screen and shrink it and darken it for the bloom process
9314 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9315 // make the bloom texture
9316 R_Bloom_MakeTexture();
9319 #if _MSC_VER >= 1400
9320 #define sscanf sscanf_s
9322 memset(uservecs, 0, sizeof(uservecs));
9323 if (r_glsl_postprocess_uservec1_enable.integer)
9324 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9325 if (r_glsl_postprocess_uservec2_enable.integer)
9326 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9327 if (r_glsl_postprocess_uservec3_enable.integer)
9328 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9329 if (r_glsl_postprocess_uservec4_enable.integer)
9330 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9332 R_ResetViewRendering2D();
9333 GL_Color(1, 1, 1, 1);
9334 GL_BlendFunc(GL_ONE, GL_ZERO);
9336 switch(vid.renderpath)
9338 case RENDERPATH_GL20:
9339 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9340 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9341 if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
9342 if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
9343 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
9344 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]);
9345 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9346 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]);
9347 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]);
9348 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]);
9349 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]);
9350 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
9351 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9352 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);
9354 case RENDERPATH_CGGL:
9356 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9357 R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9358 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_bloomstate.texture_screen);CHECKCGERROR
9359 if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_bloomstate.texture_bloom );CHECKCGERROR
9360 if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps );CHECKCGERROR
9361 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
9362 if (r_cg_permutation->fp_PixelSize ) cgGLSetParameter2f( r_cg_permutation->fp_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9363 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
9364 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
9365 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
9366 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
9367 if (r_cg_permutation->fp_Saturation ) cgGLSetParameter1f( r_cg_permutation->fp_Saturation , r_glsl_saturation.value);CHECKCGERROR
9368 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9369 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);
9372 case RENDERPATH_D3D9:
9374 // 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...
9375 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9376 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9377 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
9378 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
9379 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
9380 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9381 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9382 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9383 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9384 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9385 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9386 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
9387 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9388 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9391 case RENDERPATH_D3D10:
9392 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9394 case RENDERPATH_D3D11:
9395 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9400 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9401 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9403 case RENDERPATH_GL13:
9404 case RENDERPATH_GL11:
9405 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9407 // apply a color tint to the whole view
9408 R_ResetViewRendering2D();
9409 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9410 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9411 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9412 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9413 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9419 matrix4x4_t r_waterscrollmatrix;
9421 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9423 if (r_refdef.fog_density)
9425 r_refdef.fogcolor[0] = r_refdef.fog_red;
9426 r_refdef.fogcolor[1] = r_refdef.fog_green;
9427 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9429 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9430 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9431 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9432 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9436 VectorCopy(r_refdef.fogcolor, fogvec);
9437 // color.rgb *= ContrastBoost * SceneBrightness;
9438 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9439 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9440 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9441 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9446 void R_UpdateVariables(void)
9450 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9452 r_refdef.farclip = r_farclip_base.value;
9453 if (r_refdef.scene.worldmodel)
9454 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9455 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9457 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9458 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9459 r_refdef.polygonfactor = 0;
9460 r_refdef.polygonoffset = 0;
9461 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9462 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9464 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9465 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9466 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
9467 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9468 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9469 if (FAKELIGHT_ENABLED)
9471 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
9473 if (r_showsurfaces.integer)
9475 r_refdef.scene.rtworld = false;
9476 r_refdef.scene.rtworldshadows = false;
9477 r_refdef.scene.rtdlight = false;
9478 r_refdef.scene.rtdlightshadows = false;
9479 r_refdef.lightmapintensity = 0;
9482 if (gamemode == GAME_NEHAHRA)
9484 if (gl_fogenable.integer)
9486 r_refdef.oldgl_fogenable = true;
9487 r_refdef.fog_density = gl_fogdensity.value;
9488 r_refdef.fog_red = gl_fogred.value;
9489 r_refdef.fog_green = gl_foggreen.value;
9490 r_refdef.fog_blue = gl_fogblue.value;
9491 r_refdef.fog_alpha = 1;
9492 r_refdef.fog_start = 0;
9493 r_refdef.fog_end = gl_skyclip.value;
9494 r_refdef.fog_height = 1<<30;
9495 r_refdef.fog_fadedepth = 128;
9497 else if (r_refdef.oldgl_fogenable)
9499 r_refdef.oldgl_fogenable = false;
9500 r_refdef.fog_density = 0;
9501 r_refdef.fog_red = 0;
9502 r_refdef.fog_green = 0;
9503 r_refdef.fog_blue = 0;
9504 r_refdef.fog_alpha = 0;
9505 r_refdef.fog_start = 0;
9506 r_refdef.fog_end = 0;
9507 r_refdef.fog_height = 1<<30;
9508 r_refdef.fog_fadedepth = 128;
9512 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9513 r_refdef.fog_start = max(0, r_refdef.fog_start);
9514 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9516 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9518 if (r_refdef.fog_density && r_drawfog.integer)
9520 r_refdef.fogenabled = true;
9521 // this is the point where the fog reaches 0.9986 alpha, which we
9522 // consider a good enough cutoff point for the texture
9523 // (0.9986 * 256 == 255.6)
9524 if (r_fog_exp2.integer)
9525 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9527 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9528 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9529 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9530 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9531 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9532 R_BuildFogHeightTexture();
9533 // fog color was already set
9534 // update the fog texture
9535 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)
9536 R_BuildFogTexture();
9537 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9538 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9541 r_refdef.fogenabled = false;
9543 switch(vid.renderpath)
9545 case RENDERPATH_GL20:
9546 case RENDERPATH_CGGL:
9547 case RENDERPATH_D3D9:
9548 case RENDERPATH_D3D10:
9549 case RENDERPATH_D3D11:
9550 if(v_glslgamma.integer && !vid_gammatables_trivial)
9552 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9554 // build GLSL gamma texture
9555 #define RAMPWIDTH 256
9556 unsigned short ramp[RAMPWIDTH * 3];
9557 unsigned char rampbgr[RAMPWIDTH][4];
9560 r_texture_gammaramps_serial = vid_gammatables_serial;
9562 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9563 for(i = 0; i < RAMPWIDTH; ++i)
9565 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9566 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9567 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9570 if (r_texture_gammaramps)
9572 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9576 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9582 // remove GLSL gamma texture
9585 case RENDERPATH_GL13:
9586 case RENDERPATH_GL11:
9591 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9592 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9598 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9599 if( scenetype != r_currentscenetype ) {
9600 // store the old scenetype
9601 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9602 r_currentscenetype = scenetype;
9603 // move in the new scene
9604 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9613 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9615 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9616 if( scenetype == r_currentscenetype ) {
9617 return &r_refdef.scene;
9619 return &r_scenes_store[ scenetype ];
9628 void R_RenderView(void)
9630 if (r_timereport_active)
9631 R_TimeReport("start");
9632 r_textureframe++; // used only by R_GetCurrentTexture
9633 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9635 if(R_CompileShader_CheckStaticParms())
9638 if (!r_drawentities.integer)
9639 r_refdef.scene.numentities = 0;
9641 R_AnimCache_ClearCache();
9642 R_FrameData_NewFrame();
9644 if (r_refdef.view.isoverlay)
9646 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9647 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9648 R_TimeReport("depthclear");
9650 r_refdef.view.showdebug = false;
9652 r_waterstate.enabled = false;
9653 r_waterstate.numwaterplanes = 0;
9661 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9662 return; //Host_Error ("R_RenderView: NULL worldmodel");
9664 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9666 R_RenderView_UpdateViewVectors();
9668 R_Shadow_UpdateWorldLightSelection();
9670 R_Bloom_StartFrame();
9671 R_Water_StartFrame();
9674 if (r_timereport_active)
9675 R_TimeReport("viewsetup");
9677 R_ResetViewRendering3D();
9679 if (r_refdef.view.clear || r_refdef.fogenabled)
9681 R_ClearScreen(r_refdef.fogenabled);
9682 if (r_timereport_active)
9683 R_TimeReport("viewclear");
9685 r_refdef.view.clear = true;
9687 // this produces a bloom texture to be used in R_BlendView() later
9688 if (r_hdr.integer && r_bloomstate.bloomwidth)
9690 R_HDR_RenderBloomTexture();
9691 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9692 r_textureframe++; // used only by R_GetCurrentTexture
9695 r_refdef.view.showdebug = true;
9698 if (r_timereport_active)
9699 R_TimeReport("visibility");
9701 r_waterstate.numwaterplanes = 0;
9702 if (r_waterstate.enabled)
9703 R_RenderWaterPlanes();
9706 r_waterstate.numwaterplanes = 0;
9709 if (r_timereport_active)
9710 R_TimeReport("blendview");
9712 GL_Scissor(0, 0, vid.width, vid.height);
9713 GL_ScissorTest(false);
9718 void R_RenderWaterPlanes(void)
9720 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9722 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9723 if (r_timereport_active)
9724 R_TimeReport("waterworld");
9727 // don't let sound skip if going slow
9728 if (r_refdef.scene.extraupdate)
9731 R_DrawModelsAddWaterPlanes();
9732 if (r_timereport_active)
9733 R_TimeReport("watermodels");
9735 if (r_waterstate.numwaterplanes)
9737 R_Water_ProcessPlanes();
9738 if (r_timereport_active)
9739 R_TimeReport("waterscenes");
9743 extern void R_DrawLightningBeams (void);
9744 extern void VM_CL_AddPolygonsToMeshQueue (void);
9745 extern void R_DrawPortals (void);
9746 extern cvar_t cl_locs_show;
9747 static void R_DrawLocs(void);
9748 static void R_DrawEntityBBoxes(void);
9749 static void R_DrawModelDecals(void);
9750 extern void R_DrawModelShadows(void);
9751 extern void R_DrawModelShadowMaps(void);
9752 extern cvar_t cl_decals_newsystem;
9753 extern qboolean r_shadow_usingdeferredprepass;
9754 void R_RenderScene(void)
9756 qboolean shadowmapping = false;
9758 if (r_timereport_active)
9759 R_TimeReport("beginscene");
9761 r_refdef.stats.renders++;
9765 // don't let sound skip if going slow
9766 if (r_refdef.scene.extraupdate)
9769 R_MeshQueue_BeginScene();
9773 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);
9775 if (r_timereport_active)
9776 R_TimeReport("skystartframe");
9778 if (cl.csqc_vidvars.drawworld)
9780 // don't let sound skip if going slow
9781 if (r_refdef.scene.extraupdate)
9784 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9786 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9787 if (r_timereport_active)
9788 R_TimeReport("worldsky");
9791 if (R_DrawBrushModelsSky() && r_timereport_active)
9792 R_TimeReport("bmodelsky");
9794 if (skyrendermasked && skyrenderlater)
9796 // we have to force off the water clipping plane while rendering sky
9800 if (r_timereport_active)
9801 R_TimeReport("sky");
9805 R_AnimCache_CacheVisibleEntities();
9806 if (r_timereport_active)
9807 R_TimeReport("animation");
9809 R_Shadow_PrepareLights();
9810 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9811 R_Shadow_PrepareModelShadows();
9812 if (r_timereport_active)
9813 R_TimeReport("preparelights");
9815 if (R_Shadow_ShadowMappingEnabled())
9816 shadowmapping = true;
9818 if (r_shadow_usingdeferredprepass)
9819 R_Shadow_DrawPrepass();
9821 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9823 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9824 if (r_timereport_active)
9825 R_TimeReport("worlddepth");
9827 if (r_depthfirst.integer >= 2)
9829 R_DrawModelsDepth();
9830 if (r_timereport_active)
9831 R_TimeReport("modeldepth");
9834 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9836 R_DrawModelShadowMaps();
9837 R_ResetViewRendering3D();
9838 // don't let sound skip if going slow
9839 if (r_refdef.scene.extraupdate)
9843 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9845 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9846 if (r_timereport_active)
9847 R_TimeReport("world");
9850 // don't let sound skip if going slow
9851 if (r_refdef.scene.extraupdate)
9855 if (r_timereport_active)
9856 R_TimeReport("models");
9858 // don't let sound skip if going slow
9859 if (r_refdef.scene.extraupdate)
9862 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9864 R_DrawModelShadows();
9865 R_ResetViewRendering3D();
9866 // don't let sound skip if going slow
9867 if (r_refdef.scene.extraupdate)
9871 if (!r_shadow_usingdeferredprepass)
9873 R_Shadow_DrawLights();
9874 if (r_timereport_active)
9875 R_TimeReport("rtlights");
9878 // don't let sound skip if going slow
9879 if (r_refdef.scene.extraupdate)
9882 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9884 R_DrawModelShadows();
9885 R_ResetViewRendering3D();
9886 // don't let sound skip if going slow
9887 if (r_refdef.scene.extraupdate)
9891 if (cl.csqc_vidvars.drawworld)
9893 if (cl_decals_newsystem.integer)
9895 R_DrawModelDecals();
9896 if (r_timereport_active)
9897 R_TimeReport("modeldecals");
9902 if (r_timereport_active)
9903 R_TimeReport("decals");
9907 if (r_timereport_active)
9908 R_TimeReport("particles");
9911 if (r_timereport_active)
9912 R_TimeReport("explosions");
9914 R_DrawLightningBeams();
9915 if (r_timereport_active)
9916 R_TimeReport("lightning");
9919 VM_CL_AddPolygonsToMeshQueue();
9921 if (r_refdef.view.showdebug)
9923 if (cl_locs_show.integer)
9926 if (r_timereport_active)
9927 R_TimeReport("showlocs");
9930 if (r_drawportals.integer)
9933 if (r_timereport_active)
9934 R_TimeReport("portals");
9937 if (r_showbboxes.value > 0)
9939 R_DrawEntityBBoxes();
9940 if (r_timereport_active)
9941 R_TimeReport("bboxes");
9945 R_MeshQueue_RenderTransparent();
9946 if (r_timereport_active)
9947 R_TimeReport("drawtrans");
9949 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))
9951 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9952 if (r_timereport_active)
9953 R_TimeReport("worlddebug");
9954 R_DrawModelsDebug();
9955 if (r_timereport_active)
9956 R_TimeReport("modeldebug");
9959 if (cl.csqc_vidvars.drawworld)
9961 R_Shadow_DrawCoronas();
9962 if (r_timereport_active)
9963 R_TimeReport("coronas");
9968 GL_DepthTest(false);
9969 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9970 GL_Color(1, 1, 1, 1);
9971 qglBegin(GL_POLYGON);
9972 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
9973 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
9974 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
9975 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
9977 qglBegin(GL_POLYGON);
9978 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]);
9979 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]);
9980 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]);
9981 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]);
9983 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9987 // don't let sound skip if going slow
9988 if (r_refdef.scene.extraupdate)
9991 R_ResetViewRendering2D();
9994 static const unsigned short bboxelements[36] =
10004 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
10007 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
10009 RSurf_ActiveWorldEntity();
10011 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10012 GL_DepthMask(false);
10013 GL_DepthRange(0, 1);
10014 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10015 R_Mesh_ResetTextureState();
10017 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
10018 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
10019 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
10020 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
10021 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
10022 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
10023 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
10024 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
10025 R_FillColors(color4f, 8, cr, cg, cb, ca);
10026 if (r_refdef.fogenabled)
10028 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
10030 f1 = RSurf_FogVertex(v);
10032 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
10033 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
10034 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
10037 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
10038 R_Mesh_ResetTextureState();
10039 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10040 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
10043 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10047 prvm_edict_t *edict;
10048 prvm_prog_t *prog_save = prog;
10050 // this function draws bounding boxes of server entities
10054 GL_CullFace(GL_NONE);
10055 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10059 for (i = 0;i < numsurfaces;i++)
10061 edict = PRVM_EDICT_NUM(surfacelist[i]);
10062 switch ((int)edict->fields.server->solid)
10064 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
10065 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
10066 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
10067 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
10068 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
10069 default: Vector4Set(color, 0, 0, 0, 0.50);break;
10071 color[3] *= r_showbboxes.value;
10072 color[3] = bound(0, color[3], 1);
10073 GL_DepthTest(!r_showdisabledepthtest.integer);
10074 GL_CullFace(r_refdef.view.cullface_front);
10075 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
10081 static void R_DrawEntityBBoxes(void)
10084 prvm_edict_t *edict;
10086 prvm_prog_t *prog_save = prog;
10088 // this function draws bounding boxes of server entities
10094 for (i = 0;i < prog->num_edicts;i++)
10096 edict = PRVM_EDICT_NUM(i);
10097 if (edict->priv.server->free)
10099 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
10100 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
10102 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
10104 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
10105 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
10111 static const int nomodelelement3i[24] =
10123 static const unsigned short nomodelelement3s[24] =
10135 static const float nomodelvertex3f[6*3] =
10145 static const float nomodelcolor4f[6*4] =
10147 0.0f, 0.0f, 0.5f, 1.0f,
10148 0.0f, 0.0f, 0.5f, 1.0f,
10149 0.0f, 0.5f, 0.0f, 1.0f,
10150 0.0f, 0.5f, 0.0f, 1.0f,
10151 0.5f, 0.0f, 0.0f, 1.0f,
10152 0.5f, 0.0f, 0.0f, 1.0f
10155 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10159 float color4f[6*4];
10161 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);
10163 // this is only called once per entity so numsurfaces is always 1, and
10164 // surfacelist is always {0}, so this code does not handle batches
10166 if (rsurface.ent_flags & RENDER_ADDITIVE)
10168 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
10169 GL_DepthMask(false);
10171 else if (rsurface.colormod[3] < 1)
10173 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10174 GL_DepthMask(false);
10178 GL_BlendFunc(GL_ONE, GL_ZERO);
10179 GL_DepthMask(true);
10181 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
10182 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
10183 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
10184 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
10185 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
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_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
10207 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
10210 void R_DrawNoModel(entity_render_t *ent)
10213 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
10214 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
10215 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
10217 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
10220 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
10222 vec3_t right1, right2, diff, normal;
10224 VectorSubtract (org2, org1, normal);
10226 // calculate 'right' vector for start
10227 VectorSubtract (r_refdef.view.origin, org1, diff);
10228 CrossProduct (normal, diff, right1);
10229 VectorNormalize (right1);
10231 // calculate 'right' vector for end
10232 VectorSubtract (r_refdef.view.origin, org2, diff);
10233 CrossProduct (normal, diff, right2);
10234 VectorNormalize (right2);
10236 vert[ 0] = org1[0] + width * right1[0];
10237 vert[ 1] = org1[1] + width * right1[1];
10238 vert[ 2] = org1[2] + width * right1[2];
10239 vert[ 3] = org1[0] - width * right1[0];
10240 vert[ 4] = org1[1] - width * right1[1];
10241 vert[ 5] = org1[2] - width * right1[2];
10242 vert[ 6] = org2[0] - width * right2[0];
10243 vert[ 7] = org2[1] - width * right2[1];
10244 vert[ 8] = org2[2] - width * right2[2];
10245 vert[ 9] = org2[0] + width * right2[0];
10246 vert[10] = org2[1] + width * right2[1];
10247 vert[11] = org2[2] + width * right2[2];
10250 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)
10252 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
10253 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
10254 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
10255 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
10256 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
10257 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
10258 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
10259 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
10260 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
10261 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
10262 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
10263 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
10266 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
10271 VectorSet(v, x, y, z);
10272 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
10273 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
10275 if (i == mesh->numvertices)
10277 if (mesh->numvertices < mesh->maxvertices)
10279 VectorCopy(v, vertex3f);
10280 mesh->numvertices++;
10282 return mesh->numvertices;
10288 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
10291 int *e, element[3];
10292 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10293 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10294 e = mesh->element3i + mesh->numtriangles * 3;
10295 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
10297 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
10298 if (mesh->numtriangles < mesh->maxtriangles)
10303 mesh->numtriangles++;
10305 element[1] = element[2];
10309 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
10312 int *e, element[3];
10313 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10314 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10315 e = mesh->element3i + mesh->numtriangles * 3;
10316 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10318 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10319 if (mesh->numtriangles < mesh->maxtriangles)
10324 mesh->numtriangles++;
10326 element[1] = element[2];
10330 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10331 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10333 int planenum, planenum2;
10336 mplane_t *plane, *plane2;
10338 double temppoints[2][256*3];
10339 // figure out how large a bounding box we need to properly compute this brush
10341 for (w = 0;w < numplanes;w++)
10342 maxdist = max(maxdist, fabs(planes[w].dist));
10343 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10344 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10345 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10349 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10350 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10352 if (planenum2 == planenum)
10354 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);
10357 if (tempnumpoints < 3)
10359 // generate elements forming a triangle fan for this polygon
10360 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10364 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)
10366 texturelayer_t *layer;
10367 layer = t->currentlayers + t->currentnumlayers++;
10368 layer->type = type;
10369 layer->depthmask = depthmask;
10370 layer->blendfunc1 = blendfunc1;
10371 layer->blendfunc2 = blendfunc2;
10372 layer->texture = texture;
10373 layer->texmatrix = *matrix;
10374 layer->color[0] = r;
10375 layer->color[1] = g;
10376 layer->color[2] = b;
10377 layer->color[3] = a;
10380 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10382 if(parms[0] == 0 && parms[1] == 0)
10384 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10385 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10390 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10393 index = parms[2] + r_refdef.scene.time * parms[3];
10394 index -= floor(index);
10395 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10398 case Q3WAVEFUNC_NONE:
10399 case Q3WAVEFUNC_NOISE:
10400 case Q3WAVEFUNC_COUNT:
10403 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10404 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10405 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10406 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10407 case Q3WAVEFUNC_TRIANGLE:
10409 f = index - floor(index);
10412 else if (index < 2)
10414 else if (index < 3)
10420 f = parms[0] + parms[1] * f;
10421 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10422 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10426 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10431 matrix4x4_t matrix, temp;
10432 switch(tcmod->tcmod)
10434 case Q3TCMOD_COUNT:
10436 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10437 matrix = r_waterscrollmatrix;
10439 matrix = identitymatrix;
10441 case Q3TCMOD_ENTITYTRANSLATE:
10442 // this is used in Q3 to allow the gamecode to control texcoord
10443 // scrolling on the entity, which is not supported in darkplaces yet.
10444 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10446 case Q3TCMOD_ROTATE:
10447 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10448 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10449 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10451 case Q3TCMOD_SCALE:
10452 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10454 case Q3TCMOD_SCROLL:
10455 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10457 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10458 w = (int) tcmod->parms[0];
10459 h = (int) tcmod->parms[1];
10460 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10462 idx = (int) floor(f * w * h);
10463 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10465 case Q3TCMOD_STRETCH:
10466 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10467 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10469 case Q3TCMOD_TRANSFORM:
10470 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
10471 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
10472 VectorSet(tcmat + 6, 0 , 0 , 1);
10473 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
10474 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10476 case Q3TCMOD_TURBULENT:
10477 // this is handled in the RSurf_PrepareVertices function
10478 matrix = identitymatrix;
10482 Matrix4x4_Concat(texmatrix, &matrix, &temp);
10485 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10487 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10488 char name[MAX_QPATH];
10489 skinframe_t *skinframe;
10490 unsigned char pixels[296*194];
10491 strlcpy(cache->name, skinname, sizeof(cache->name));
10492 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10493 if (developer_loading.integer)
10494 Con_Printf("loading %s\n", name);
10495 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10496 if (!skinframe || !skinframe->base)
10499 fs_offset_t filesize;
10501 f = FS_LoadFile(name, tempmempool, true, &filesize);
10504 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10505 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10509 cache->skinframe = skinframe;
10512 texture_t *R_GetCurrentTexture(texture_t *t)
10515 const entity_render_t *ent = rsurface.entity;
10516 dp_model_t *model = ent->model;
10517 q3shaderinfo_layer_tcmod_t *tcmod;
10519 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10520 return t->currentframe;
10521 t->update_lastrenderframe = r_textureframe;
10522 t->update_lastrenderentity = (void *)ent;
10524 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10525 t->camera_entity = ent->entitynumber;
10527 t->camera_entity = 0;
10529 // switch to an alternate material if this is a q1bsp animated material
10531 texture_t *texture = t;
10532 int s = rsurface.ent_skinnum;
10533 if ((unsigned int)s >= (unsigned int)model->numskins)
10535 if (model->skinscenes)
10537 if (model->skinscenes[s].framecount > 1)
10538 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10540 s = model->skinscenes[s].firstframe;
10543 t = t + s * model->num_surfaces;
10546 // use an alternate animation if the entity's frame is not 0,
10547 // and only if the texture has an alternate animation
10548 if (rsurface.ent_alttextures && t->anim_total[1])
10549 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10551 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10553 texture->currentframe = t;
10556 // update currentskinframe to be a qw skin or animation frame
10557 if (rsurface.ent_qwskin >= 0)
10559 i = rsurface.ent_qwskin;
10560 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10562 r_qwskincache_size = cl.maxclients;
10564 Mem_Free(r_qwskincache);
10565 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10567 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10568 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10569 t->currentskinframe = r_qwskincache[i].skinframe;
10570 if (t->currentskinframe == NULL)
10571 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10573 else if (t->numskinframes >= 2)
10574 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10575 if (t->backgroundnumskinframes >= 2)
10576 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10578 t->currentmaterialflags = t->basematerialflags;
10579 t->currentalpha = rsurface.colormod[3];
10580 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10581 t->currentalpha *= r_wateralpha.value;
10582 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10583 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10584 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10585 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10586 if (!(rsurface.ent_flags & RENDER_LIGHT))
10587 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10588 else if (FAKELIGHT_ENABLED)
10590 // no modellight if using fakelight for the map
10592 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10594 // pick a model lighting mode
10595 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10596 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10598 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10600 if (rsurface.ent_flags & RENDER_ADDITIVE)
10601 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10602 else if (t->currentalpha < 1)
10603 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10604 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10605 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10606 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10607 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10608 if (t->backgroundnumskinframes)
10609 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10610 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10612 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10613 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10616 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10617 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10618 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10620 // there is no tcmod
10621 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10623 t->currenttexmatrix = r_waterscrollmatrix;
10624 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10626 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10628 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10629 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10632 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10633 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10634 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10635 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10637 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10638 if (t->currentskinframe->qpixels)
10639 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10640 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10641 if (!t->basetexture)
10642 t->basetexture = r_texture_notexture;
10643 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10644 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10645 t->nmaptexture = t->currentskinframe->nmap;
10646 if (!t->nmaptexture)
10647 t->nmaptexture = r_texture_blanknormalmap;
10648 t->glosstexture = r_texture_black;
10649 t->glowtexture = t->currentskinframe->glow;
10650 t->fogtexture = t->currentskinframe->fog;
10651 t->reflectmasktexture = t->currentskinframe->reflect;
10652 if (t->backgroundnumskinframes)
10654 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10655 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10656 t->backgroundglosstexture = r_texture_black;
10657 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10658 if (!t->backgroundnmaptexture)
10659 t->backgroundnmaptexture = r_texture_blanknormalmap;
10663 t->backgroundbasetexture = r_texture_white;
10664 t->backgroundnmaptexture = r_texture_blanknormalmap;
10665 t->backgroundglosstexture = r_texture_black;
10666 t->backgroundglowtexture = NULL;
10668 t->specularpower = r_shadow_glossexponent.value;
10669 // TODO: store reference values for these in the texture?
10670 t->specularscale = 0;
10671 if (r_shadow_gloss.integer > 0)
10673 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10675 if (r_shadow_glossintensity.value > 0)
10677 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10678 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10679 t->specularscale = r_shadow_glossintensity.value;
10682 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10684 t->glosstexture = r_texture_white;
10685 t->backgroundglosstexture = r_texture_white;
10686 t->specularscale = r_shadow_gloss2intensity.value;
10687 t->specularpower = r_shadow_gloss2exponent.value;
10690 t->specularscale *= t->specularscalemod;
10691 t->specularpower *= t->specularpowermod;
10693 // lightmaps mode looks bad with dlights using actual texturing, so turn
10694 // off the colormap and glossmap, but leave the normalmap on as it still
10695 // accurately represents the shading involved
10696 if (gl_lightmaps.integer)
10698 t->basetexture = r_texture_grey128;
10699 t->pantstexture = r_texture_black;
10700 t->shirttexture = r_texture_black;
10701 t->nmaptexture = r_texture_blanknormalmap;
10702 t->glosstexture = r_texture_black;
10703 t->glowtexture = NULL;
10704 t->fogtexture = NULL;
10705 t->reflectmasktexture = NULL;
10706 t->backgroundbasetexture = NULL;
10707 t->backgroundnmaptexture = r_texture_blanknormalmap;
10708 t->backgroundglosstexture = r_texture_black;
10709 t->backgroundglowtexture = NULL;
10710 t->specularscale = 0;
10711 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10714 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10715 VectorClear(t->dlightcolor);
10716 t->currentnumlayers = 0;
10717 if (t->currentmaterialflags & MATERIALFLAG_WALL)
10719 int blendfunc1, blendfunc2;
10720 qboolean depthmask;
10721 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10723 blendfunc1 = GL_SRC_ALPHA;
10724 blendfunc2 = GL_ONE;
10726 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10728 blendfunc1 = GL_SRC_ALPHA;
10729 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10731 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10733 blendfunc1 = t->customblendfunc[0];
10734 blendfunc2 = t->customblendfunc[1];
10738 blendfunc1 = GL_ONE;
10739 blendfunc2 = GL_ZERO;
10741 // don't colormod evilblend textures
10742 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10743 VectorSet(t->lightmapcolor, 1, 1, 1);
10744 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10745 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10747 // fullbright is not affected by r_refdef.lightmapintensity
10748 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]);
10749 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10750 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]);
10751 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10752 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]);
10756 vec3_t ambientcolor;
10758 // set the color tint used for lights affecting this surface
10759 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10761 // q3bsp has no lightmap updates, so the lightstylevalue that
10762 // would normally be baked into the lightmap must be
10763 // applied to the color
10764 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10765 if (model->type == mod_brushq3)
10766 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10767 colorscale *= r_refdef.lightmapintensity;
10768 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10769 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10770 // basic lit geometry
10771 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]);
10772 // add pants/shirt if needed
10773 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10774 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]);
10775 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10776 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]);
10777 // now add ambient passes if needed
10778 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10780 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]);
10781 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10782 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]);
10783 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10784 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]);
10787 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10788 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]);
10789 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10791 // if this is opaque use alpha blend which will darken the earlier
10794 // if this is an alpha blended material, all the earlier passes
10795 // were darkened by fog already, so we only need to add the fog
10796 // color ontop through the fog mask texture
10798 // if this is an additive blended material, all the earlier passes
10799 // were darkened by fog already, and we should not add fog color
10800 // (because the background was not darkened, there is no fog color
10801 // that was lost behind it).
10802 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]);
10806 return t->currentframe;
10809 rsurfacestate_t rsurface;
10811 void R_Mesh_ResizeArrays(int newvertices)
10813 unsigned char *base;
10815 if (rsurface.array_size >= newvertices)
10817 if (rsurface.array_base)
10818 Mem_Free(rsurface.array_base);
10819 rsurface.array_size = (newvertices + 1023) & ~1023;
10821 size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10822 size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10823 size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10824 size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10825 size += rsurface.array_size * sizeof(float[3]);
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[4]);
10834 size += rsurface.array_size * sizeof(float[2]);
10835 size += rsurface.array_size * sizeof(float[2]);
10836 size += rsurface.array_size * sizeof(float[4]);
10837 size += rsurface.array_size * sizeof(int[3]);
10838 size += rsurface.array_size * sizeof(unsigned short[3]);
10839 rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
10840 rsurface.array_modelvertexmesh = (r_vertexmesh_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10841 rsurface.array_batchvertexmesh = (r_vertexmesh_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10842 rsurface.array_modelvertexposition = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10843 rsurface.array_batchvertexposition = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10844 rsurface.array_modelvertex3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10845 rsurface.array_modelsvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10846 rsurface.array_modeltvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10847 rsurface.array_modelnormal3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10848 rsurface.array_batchvertex3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10849 rsurface.array_batchsvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10850 rsurface.array_batchtvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10851 rsurface.array_batchnormal3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10852 rsurface.array_batchlightmapcolor4f = (float *)base;base += rsurface.array_size * sizeof(float[4]);
10853 rsurface.array_batchtexcoordtexture2f = (float *)base;base += rsurface.array_size * sizeof(float[2]);
10854 rsurface.array_batchtexcoordlightmap2f = (float *)base;base += rsurface.array_size * sizeof(float[2]);
10855 rsurface.array_passcolor4f = (float *)base;base += rsurface.array_size * sizeof(float[4]);
10856 rsurface.array_batchelement3i = (int *)base;base += rsurface.array_size * sizeof(int[3]);
10857 rsurface.array_batchelement3s = (unsigned short *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
10860 void RSurf_ActiveWorldEntity(void)
10862 dp_model_t *model = r_refdef.scene.worldmodel;
10863 //if (rsurface.entity == r_refdef.scene.worldentity)
10865 rsurface.entity = r_refdef.scene.worldentity;
10866 rsurface.skeleton = NULL;
10867 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10868 rsurface.ent_skinnum = 0;
10869 rsurface.ent_qwskin = -1;
10870 rsurface.ent_shadertime = 0;
10871 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10872 R_Mesh_ResizeArrays(max(model->surfmesh.num_vertices, model->surfmesh.num_triangles));
10873 rsurface.matrix = identitymatrix;
10874 rsurface.inversematrix = identitymatrix;
10875 rsurface.matrixscale = 1;
10876 rsurface.inversematrixscale = 1;
10877 R_EntityMatrix(&identitymatrix);
10878 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10879 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10880 rsurface.fograngerecip = r_refdef.fograngerecip;
10881 rsurface.fogheightfade = r_refdef.fogheightfade;
10882 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10883 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10884 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10885 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10886 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10887 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10888 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10889 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10890 rsurface.colormod[3] = 1;
10891 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);
10892 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10893 rsurface.frameblend[0].lerp = 1;
10894 rsurface.ent_alttextures = false;
10895 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10896 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10897 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
10898 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10899 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10900 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10901 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10902 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10903 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10904 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10905 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10906 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
10907 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10908 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10909 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
10910 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10911 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10912 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
10913 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10914 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10915 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
10916 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10917 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10918 rsurface.modelelement3i = model->surfmesh.data_element3i;
10919 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10920 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10921 rsurface.modelelement3s = model->surfmesh.data_element3s;
10922 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10923 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10924 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10925 rsurface.modelnumvertices = model->surfmesh.num_vertices;
10926 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10927 rsurface.modelsurfaces = model->data_surfaces;
10928 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10929 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10930 rsurface.modelvertexposition = model->surfmesh.vertexposition;
10931 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10932 rsurface.modelgeneratedvertex = false;
10933 rsurface.batchgeneratedvertex = false;
10934 rsurface.batchfirstvertex = 0;
10935 rsurface.batchnumvertices = 0;
10936 rsurface.batchfirsttriangle = 0;
10937 rsurface.batchnumtriangles = 0;
10938 rsurface.batchvertex3f = NULL;
10939 rsurface.batchvertex3f_vertexbuffer = NULL;
10940 rsurface.batchvertex3f_bufferoffset = 0;
10941 rsurface.batchsvector3f = NULL;
10942 rsurface.batchsvector3f_vertexbuffer = NULL;
10943 rsurface.batchsvector3f_bufferoffset = 0;
10944 rsurface.batchtvector3f = NULL;
10945 rsurface.batchtvector3f_vertexbuffer = NULL;
10946 rsurface.batchtvector3f_bufferoffset = 0;
10947 rsurface.batchnormal3f = NULL;
10948 rsurface.batchnormal3f_vertexbuffer = NULL;
10949 rsurface.batchnormal3f_bufferoffset = 0;
10950 rsurface.batchlightmapcolor4f = NULL;
10951 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10952 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10953 rsurface.batchtexcoordtexture2f = NULL;
10954 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10955 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10956 rsurface.batchtexcoordlightmap2f = NULL;
10957 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10958 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10959 rsurface.batchvertexmesh = NULL;
10960 rsurface.batchvertexmeshbuffer = NULL;
10961 rsurface.batchvertexposition = NULL;
10962 rsurface.batchvertexpositionbuffer = NULL;
10963 rsurface.batchelement3i = NULL;
10964 rsurface.batchelement3i_indexbuffer = NULL;
10965 rsurface.batchelement3i_bufferoffset = 0;
10966 rsurface.batchelement3s = NULL;
10967 rsurface.batchelement3s_indexbuffer = NULL;
10968 rsurface.batchelement3s_bufferoffset = 0;
10969 rsurface.passcolor4f = NULL;
10970 rsurface.passcolor4f_vertexbuffer = NULL;
10971 rsurface.passcolor4f_bufferoffset = 0;
10974 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10976 dp_model_t *model = ent->model;
10977 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10979 rsurface.entity = (entity_render_t *)ent;
10980 rsurface.skeleton = ent->skeleton;
10981 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10982 rsurface.ent_skinnum = ent->skinnum;
10983 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;
10984 rsurface.ent_shadertime = ent->shadertime;
10985 rsurface.ent_flags = ent->flags;
10986 R_Mesh_ResizeArrays(max(model->surfmesh.num_vertices, model->surfmesh.num_triangles));
10987 rsurface.matrix = ent->matrix;
10988 rsurface.inversematrix = ent->inversematrix;
10989 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10990 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10991 R_EntityMatrix(&rsurface.matrix);
10992 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10993 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10994 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10995 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10996 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10997 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10998 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10999 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
11000 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
11001 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
11002 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
11003 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
11004 rsurface.colormod[3] = ent->alpha;
11005 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
11006 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
11007 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
11008 rsurface.basepolygonfactor = r_refdef.polygonfactor;
11009 rsurface.basepolygonoffset = r_refdef.polygonoffset;
11010 if (ent->model->brush.submodel && !prepass)
11012 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
11013 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
11015 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
11017 if (ent->animcache_vertex3f && !r_framedata_failed)
11019 rsurface.modelvertex3f = ent->animcache_vertex3f;
11020 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
11021 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
11022 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
11023 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
11024 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
11025 rsurface.modelvertexposition = ent->animcache_vertexposition;
11026 rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
11028 else if (wanttangents)
11030 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11031 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11032 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11033 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11034 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
11035 rsurface.modelvertexmesh = NULL;
11036 rsurface.modelvertexmeshbuffer = NULL;
11037 rsurface.modelvertexposition = NULL;
11038 rsurface.modelvertexpositionbuffer = NULL;
11040 else if (wantnormals)
11042 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11043 rsurface.modelsvector3f = NULL;
11044 rsurface.modeltvector3f = NULL;
11045 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11046 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
11047 rsurface.modelvertexmesh = NULL;
11048 rsurface.modelvertexmeshbuffer = NULL;
11049 rsurface.modelvertexposition = NULL;
11050 rsurface.modelvertexpositionbuffer = NULL;
11054 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11055 rsurface.modelsvector3f = NULL;
11056 rsurface.modeltvector3f = NULL;
11057 rsurface.modelnormal3f = NULL;
11058 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
11059 rsurface.modelvertexmesh = NULL;
11060 rsurface.modelvertexmeshbuffer = NULL;
11061 rsurface.modelvertexposition = NULL;
11062 rsurface.modelvertexpositionbuffer = NULL;
11064 rsurface.modelvertex3f_vertexbuffer = 0;
11065 rsurface.modelvertex3f_bufferoffset = 0;
11066 rsurface.modelsvector3f_vertexbuffer = 0;
11067 rsurface.modelsvector3f_bufferoffset = 0;
11068 rsurface.modeltvector3f_vertexbuffer = 0;
11069 rsurface.modeltvector3f_bufferoffset = 0;
11070 rsurface.modelnormal3f_vertexbuffer = 0;
11071 rsurface.modelnormal3f_bufferoffset = 0;
11072 rsurface.modelgeneratedvertex = true;
11076 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
11077 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11078 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
11079 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
11080 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11081 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
11082 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
11083 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11084 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
11085 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
11086 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11087 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
11088 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
11089 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
11090 rsurface.modelvertexposition = model->surfmesh.vertexposition;
11091 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
11092 rsurface.modelgeneratedvertex = false;
11094 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
11095 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11096 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11097 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
11098 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11099 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11100 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
11101 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11102 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11103 rsurface.modelelement3i = model->surfmesh.data_element3i;
11104 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11105 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11106 rsurface.modelelement3s = model->surfmesh.data_element3s;
11107 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11108 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11109 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11110 rsurface.modelnumvertices = model->surfmesh.num_vertices;
11111 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11112 rsurface.modelsurfaces = model->data_surfaces;
11113 rsurface.batchgeneratedvertex = false;
11114 rsurface.batchfirstvertex = 0;
11115 rsurface.batchnumvertices = 0;
11116 rsurface.batchfirsttriangle = 0;
11117 rsurface.batchnumtriangles = 0;
11118 rsurface.batchvertex3f = NULL;
11119 rsurface.batchvertex3f_vertexbuffer = NULL;
11120 rsurface.batchvertex3f_bufferoffset = 0;
11121 rsurface.batchsvector3f = NULL;
11122 rsurface.batchsvector3f_vertexbuffer = NULL;
11123 rsurface.batchsvector3f_bufferoffset = 0;
11124 rsurface.batchtvector3f = NULL;
11125 rsurface.batchtvector3f_vertexbuffer = NULL;
11126 rsurface.batchtvector3f_bufferoffset = 0;
11127 rsurface.batchnormal3f = NULL;
11128 rsurface.batchnormal3f_vertexbuffer = NULL;
11129 rsurface.batchnormal3f_bufferoffset = 0;
11130 rsurface.batchlightmapcolor4f = NULL;
11131 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11132 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11133 rsurface.batchtexcoordtexture2f = NULL;
11134 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11135 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11136 rsurface.batchtexcoordlightmap2f = NULL;
11137 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11138 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11139 rsurface.batchvertexmesh = NULL;
11140 rsurface.batchvertexmeshbuffer = NULL;
11141 rsurface.batchvertexposition = NULL;
11142 rsurface.batchvertexpositionbuffer = NULL;
11143 rsurface.batchelement3i = NULL;
11144 rsurface.batchelement3i_indexbuffer = NULL;
11145 rsurface.batchelement3i_bufferoffset = 0;
11146 rsurface.batchelement3s = NULL;
11147 rsurface.batchelement3s_indexbuffer = NULL;
11148 rsurface.batchelement3s_bufferoffset = 0;
11149 rsurface.passcolor4f = NULL;
11150 rsurface.passcolor4f_vertexbuffer = NULL;
11151 rsurface.passcolor4f_bufferoffset = 0;
11154 void RSurf_ActiveCustomEntity(const matrix4x4_t *matrix, const matrix4x4_t *inversematrix, int entflags, double shadertime, float r, float g, float b, float a, int numvertices, const float *vertex3f, const float *texcoord2f, const float *normal3f, const float *svector3f, const float *tvector3f, const float *color4f, int numtriangles, const int *element3i, const unsigned short *element3s, qboolean wantnormals, qboolean wanttangents)
11158 rsurface.entity = r_refdef.scene.worldentity;
11159 rsurface.skeleton = NULL;
11160 rsurface.ent_skinnum = 0;
11161 rsurface.ent_qwskin = -1;
11162 rsurface.ent_shadertime = shadertime;
11163 rsurface.ent_flags = entflags;
11164 rsurface.modelnumvertices = numvertices;
11165 rsurface.modelnumtriangles = numtriangles;
11166 R_Mesh_ResizeArrays(max(rsurface.modelnumvertices, rsurface.modelnumtriangles));
11167 rsurface.matrix = *matrix;
11168 rsurface.inversematrix = *inversematrix;
11169 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11170 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11171 R_EntityMatrix(&rsurface.matrix);
11172 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11173 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11174 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11175 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11176 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11177 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11178 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11179 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11180 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11181 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11182 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11183 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
11184 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);
11185 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11186 rsurface.frameblend[0].lerp = 1;
11187 rsurface.ent_alttextures = false;
11188 rsurface.basepolygonfactor = r_refdef.polygonfactor;
11189 rsurface.basepolygonoffset = r_refdef.polygonoffset;
11192 rsurface.modelvertex3f = vertex3f;
11193 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
11194 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
11195 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11197 else if (wantnormals)
11199 rsurface.modelvertex3f = vertex3f;
11200 rsurface.modelsvector3f = NULL;
11201 rsurface.modeltvector3f = NULL;
11202 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11206 rsurface.modelvertex3f = vertex3f;
11207 rsurface.modelsvector3f = NULL;
11208 rsurface.modeltvector3f = NULL;
11209 rsurface.modelnormal3f = NULL;
11211 rsurface.modelvertexmesh = NULL;
11212 rsurface.modelvertexmeshbuffer = NULL;
11213 rsurface.modelvertexposition = NULL;
11214 rsurface.modelvertexpositionbuffer = NULL;
11215 rsurface.modelvertex3f_vertexbuffer = 0;
11216 rsurface.modelvertex3f_bufferoffset = 0;
11217 rsurface.modelsvector3f_vertexbuffer = 0;
11218 rsurface.modelsvector3f_bufferoffset = 0;
11219 rsurface.modeltvector3f_vertexbuffer = 0;
11220 rsurface.modeltvector3f_bufferoffset = 0;
11221 rsurface.modelnormal3f_vertexbuffer = 0;
11222 rsurface.modelnormal3f_bufferoffset = 0;
11223 rsurface.modelgeneratedvertex = true;
11224 rsurface.modellightmapcolor4f = color4f;
11225 rsurface.modellightmapcolor4f_vertexbuffer = 0;
11226 rsurface.modellightmapcolor4f_bufferoffset = 0;
11227 rsurface.modeltexcoordtexture2f = texcoord2f;
11228 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
11229 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
11230 rsurface.modeltexcoordlightmap2f = NULL;
11231 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
11232 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
11233 rsurface.modelelement3i = element3i;
11234 rsurface.modelelement3i_indexbuffer = NULL;
11235 rsurface.modelelement3i_bufferoffset = 0;
11236 rsurface.modelelement3s = element3s;
11237 rsurface.modelelement3s_indexbuffer = NULL;
11238 rsurface.modelelement3s_bufferoffset = 0;
11239 rsurface.modellightmapoffsets = NULL;
11240 rsurface.modelsurfaces = NULL;
11241 rsurface.batchgeneratedvertex = false;
11242 rsurface.batchfirstvertex = 0;
11243 rsurface.batchnumvertices = 0;
11244 rsurface.batchfirsttriangle = 0;
11245 rsurface.batchnumtriangles = 0;
11246 rsurface.batchvertex3f = NULL;
11247 rsurface.batchvertex3f_vertexbuffer = NULL;
11248 rsurface.batchvertex3f_bufferoffset = 0;
11249 rsurface.batchsvector3f = NULL;
11250 rsurface.batchsvector3f_vertexbuffer = NULL;
11251 rsurface.batchsvector3f_bufferoffset = 0;
11252 rsurface.batchtvector3f = NULL;
11253 rsurface.batchtvector3f_vertexbuffer = NULL;
11254 rsurface.batchtvector3f_bufferoffset = 0;
11255 rsurface.batchnormal3f = NULL;
11256 rsurface.batchnormal3f_vertexbuffer = NULL;
11257 rsurface.batchnormal3f_bufferoffset = 0;
11258 rsurface.batchlightmapcolor4f = NULL;
11259 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11260 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11261 rsurface.batchtexcoordtexture2f = NULL;
11262 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11263 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11264 rsurface.batchtexcoordlightmap2f = NULL;
11265 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11266 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11267 rsurface.batchvertexmesh = NULL;
11268 rsurface.batchvertexmeshbuffer = NULL;
11269 rsurface.batchvertexposition = NULL;
11270 rsurface.batchvertexpositionbuffer = NULL;
11271 rsurface.batchelement3i = NULL;
11272 rsurface.batchelement3i_indexbuffer = NULL;
11273 rsurface.batchelement3i_bufferoffset = 0;
11274 rsurface.batchelement3s = NULL;
11275 rsurface.batchelement3s_indexbuffer = NULL;
11276 rsurface.batchelement3s_bufferoffset = 0;
11277 rsurface.passcolor4f = NULL;
11278 rsurface.passcolor4f_vertexbuffer = NULL;
11279 rsurface.passcolor4f_bufferoffset = 0;
11281 if (rsurface.modelnumvertices && rsurface.modelelement3i)
11283 if ((wantnormals || wanttangents) && !normal3f)
11285 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
11286 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11288 if (wanttangents && !svector3f)
11290 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);
11291 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11292 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11296 // now convert arrays into vertexmesh structs
11297 for (i = 0;i < numvertices;i++)
11299 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexposition[i].vertex3f);
11300 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexmesh[i].vertex3f);
11301 if (rsurface.modelsvector3f)
11302 VectorCopy(rsurface.modelsvector3f + 3*i, rsurface.array_modelvertexmesh[i].svector3f);
11303 if (rsurface.modeltvector3f)
11304 VectorCopy(rsurface.modeltvector3f + 3*i, rsurface.array_modelvertexmesh[i].tvector3f);
11305 if (rsurface.modelnormal3f)
11306 VectorCopy(rsurface.modelnormal3f + 3*i, rsurface.array_modelvertexmesh[i].normal3f);
11307 if (rsurface.modellightmapcolor4f)
11308 Vector4Scale(rsurface.modellightmapcolor4f + 4*i, 255.0f, rsurface.array_modelvertexmesh[i].color4ub);
11309 if (rsurface.modeltexcoordtexture2f)
11310 Vector2Copy(rsurface.modeltexcoordtexture2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordtexture2f);
11311 if (rsurface.modeltexcoordlightmap2f)
11312 Vector2Copy(rsurface.modeltexcoordlightmap2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordlightmap2f);
11316 float RSurf_FogPoint(const float *v)
11318 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11319 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11320 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11321 float FogHeightFade = r_refdef.fogheightfade;
11323 unsigned int fogmasktableindex;
11324 if (r_refdef.fogplaneviewabove)
11325 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11327 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11328 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11329 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11332 float RSurf_FogVertex(const float *v)
11334 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11335 float FogPlaneViewDist = rsurface.fogplaneviewdist;
11336 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11337 float FogHeightFade = rsurface.fogheightfade;
11339 unsigned int fogmasktableindex;
11340 if (r_refdef.fogplaneviewabove)
11341 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11343 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11344 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11345 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11348 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11351 for (i = 0;i < numelements;i++)
11352 outelement3i[i] = inelement3i[i] + adjust;
11355 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11356 extern cvar_t gl_vbo;
11357 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11365 int surfacefirsttriangle;
11366 int surfacenumtriangles;
11367 int surfacefirstvertex;
11368 int surfaceendvertex;
11369 int surfacenumvertices;
11373 qboolean dynamicvertex;
11377 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11378 float waveparms[4];
11379 q3shaderinfo_deform_t *deform;
11380 const msurface_t *surface, *firstsurface;
11381 r_vertexposition_t *vertexposition;
11382 r_vertexmesh_t *vertexmesh;
11383 if (!texturenumsurfaces)
11385 // find vertex range of this surface batch
11387 firstsurface = texturesurfacelist[0];
11388 firsttriangle = firstsurface->num_firsttriangle;
11390 firstvertex = endvertex = firstsurface->num_firstvertex;
11391 for (i = 0;i < texturenumsurfaces;i++)
11393 surface = texturesurfacelist[i];
11394 if (surface != firstsurface + i)
11396 surfacefirstvertex = surface->num_firstvertex;
11397 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11398 surfacenumtriangles = surface->num_triangles;
11399 if (firstvertex > surfacefirstvertex)
11400 firstvertex = surfacefirstvertex;
11401 if (endvertex < surfaceendvertex)
11402 endvertex = surfaceendvertex;
11403 numtriangles += surfacenumtriangles;
11408 // we now know the vertex range used, and if there are any gaps in it
11409 rsurface.batchfirstvertex = firstvertex;
11410 rsurface.batchnumvertices = endvertex - firstvertex;
11411 rsurface.batchfirsttriangle = firsttriangle;
11412 rsurface.batchnumtriangles = numtriangles;
11414 // this variable holds flags for which properties have been updated that
11415 // may require regenerating vertexmesh or vertexposition arrays...
11418 // check if any dynamic vertex processing must occur
11419 dynamicvertex = false;
11421 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11422 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
11423 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11425 switch (deform->deform)
11428 case Q3DEFORM_PROJECTIONSHADOW:
11429 case Q3DEFORM_TEXT0:
11430 case Q3DEFORM_TEXT1:
11431 case Q3DEFORM_TEXT2:
11432 case Q3DEFORM_TEXT3:
11433 case Q3DEFORM_TEXT4:
11434 case Q3DEFORM_TEXT5:
11435 case Q3DEFORM_TEXT6:
11436 case Q3DEFORM_TEXT7:
11437 case Q3DEFORM_NONE:
11439 case Q3DEFORM_AUTOSPRITE:
11440 dynamicvertex = true;
11441 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11442 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11444 case Q3DEFORM_AUTOSPRITE2:
11445 dynamicvertex = true;
11446 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11447 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11449 case Q3DEFORM_NORMAL:
11450 dynamicvertex = true;
11451 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11452 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11454 case Q3DEFORM_WAVE:
11455 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11456 break; // if wavefunc is a nop, ignore this transform
11457 dynamicvertex = true;
11458 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11459 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11461 case Q3DEFORM_BULGE:
11462 dynamicvertex = true;
11463 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11464 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11466 case Q3DEFORM_MOVE:
11467 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11468 break; // if wavefunc is a nop, ignore this transform
11469 dynamicvertex = true;
11470 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11471 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
11475 switch(rsurface.texture->tcgen.tcgen)
11478 case Q3TCGEN_TEXTURE:
11480 case Q3TCGEN_LIGHTMAP:
11481 dynamicvertex = true;
11482 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11483 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11485 case Q3TCGEN_VECTOR:
11486 dynamicvertex = true;
11487 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11488 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11490 case Q3TCGEN_ENVIRONMENT:
11491 dynamicvertex = true;
11492 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11493 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11496 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11498 dynamicvertex = true;
11499 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11500 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11503 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11505 dynamicvertex = true;
11506 batchneed |= BATCHNEED_NOGAPS;
11507 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11510 if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11512 dynamicvertex = true;
11513 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11514 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
11517 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11519 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11520 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
11521 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
11522 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
11523 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11524 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11525 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11528 // when the model data has no vertex buffer (dynamic mesh), we need to
11530 if (!rsurface.modelvertexmeshbuffer)
11531 batchneed |= BATCHNEED_NOGAPS;
11533 // if needsupdate, we have to do a dynamic vertex batch for sure
11534 if (needsupdate & batchneed)
11535 dynamicvertex = true;
11537 // see if we need to build vertexmesh from arrays
11538 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11539 dynamicvertex = true;
11541 // see if we need to build vertexposition from arrays
11542 if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
11543 dynamicvertex = true;
11545 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11546 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11547 dynamicvertex = true;
11549 // if there is a chance of animated vertex colors, it's a dynamic batch
11550 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11551 dynamicvertex = true;
11553 rsurface.batchvertex3f = rsurface.modelvertex3f;
11554 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11555 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11556 rsurface.batchsvector3f = rsurface.modelsvector3f;
11557 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11558 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11559 rsurface.batchtvector3f = rsurface.modeltvector3f;
11560 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11561 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11562 rsurface.batchnormal3f = rsurface.modelnormal3f;
11563 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11564 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11565 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11566 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
11567 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11568 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11569 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
11570 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
11571 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11572 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11573 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11574 rsurface.batchvertexposition = rsurface.modelvertexposition;
11575 rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
11576 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11577 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11578 rsurface.batchelement3i = rsurface.modelelement3i;
11579 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11580 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11581 rsurface.batchelement3s = rsurface.modelelement3s;
11582 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11583 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11585 // if any dynamic vertex processing has to occur in software, we copy the
11586 // entire surface list together before processing to rebase the vertices
11587 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11589 // if any gaps exist and we do not have a static vertex buffer, we have to
11590 // copy the surface list together to avoid wasting upload bandwidth on the
11591 // vertices in the gaps.
11593 // if gaps exist and we have a static vertex buffer, we still have to
11594 // combine the index buffer ranges into one dynamic index buffer.
11596 // in all cases we end up with data that can be drawn in one call.
11598 if (!dynamicvertex)
11600 // static vertex data, just set pointers...
11601 rsurface.batchgeneratedvertex = false;
11602 // if there are gaps, we want to build a combined index buffer,
11603 // otherwise use the original static buffer with an appropriate offset
11608 for (i = 0;i < texturenumsurfaces;i++)
11610 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11611 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11612 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11613 numtriangles += surfacenumtriangles;
11615 rsurface.batchelement3i = rsurface.array_batchelement3i;
11616 rsurface.batchelement3i_indexbuffer = NULL;
11617 rsurface.batchelement3i_bufferoffset = 0;
11618 rsurface.batchelement3s = NULL;
11619 rsurface.batchelement3s_indexbuffer = NULL;
11620 rsurface.batchelement3s_bufferoffset = 0;
11621 if (endvertex <= 65536)
11623 rsurface.batchelement3s = rsurface.array_batchelement3s;
11624 for (i = 0;i < numtriangles*3;i++)
11625 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11627 rsurface.batchfirsttriangle = firsttriangle;
11628 rsurface.batchnumtriangles = numtriangles;
11633 // something needs software processing, do it for real...
11634 // we only directly handle interleaved array data in this case...
11635 rsurface.batchgeneratedvertex = true;
11637 // now copy the vertex data into a combined array and make an index array
11638 // (this is what Quake3 does all the time)
11639 //if (gaps || rsurface.batchfirstvertex)
11641 rsurface.batchvertexposition = NULL;
11642 rsurface.batchvertexpositionbuffer = NULL;
11643 rsurface.batchvertexmesh = NULL;
11644 rsurface.batchvertexmeshbuffer = NULL;
11645 rsurface.batchvertex3f = NULL;
11646 rsurface.batchvertex3f_vertexbuffer = NULL;
11647 rsurface.batchvertex3f_bufferoffset = 0;
11648 rsurface.batchsvector3f = NULL;
11649 rsurface.batchsvector3f_vertexbuffer = NULL;
11650 rsurface.batchsvector3f_bufferoffset = 0;
11651 rsurface.batchtvector3f = NULL;
11652 rsurface.batchtvector3f_vertexbuffer = NULL;
11653 rsurface.batchtvector3f_bufferoffset = 0;
11654 rsurface.batchnormal3f = NULL;
11655 rsurface.batchnormal3f_vertexbuffer = NULL;
11656 rsurface.batchnormal3f_bufferoffset = 0;
11657 rsurface.batchlightmapcolor4f = NULL;
11658 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11659 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11660 rsurface.batchtexcoordtexture2f = NULL;
11661 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11662 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11663 rsurface.batchtexcoordlightmap2f = NULL;
11664 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11665 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11666 rsurface.batchelement3i = rsurface.array_batchelement3i;
11667 rsurface.batchelement3i_indexbuffer = NULL;
11668 rsurface.batchelement3i_bufferoffset = 0;
11669 rsurface.batchelement3s = NULL;
11670 rsurface.batchelement3s_indexbuffer = NULL;
11671 rsurface.batchelement3s_bufferoffset = 0;
11672 // we'll only be setting up certain arrays as needed
11673 if (batchneed & BATCHNEED_VERTEXPOSITION)
11674 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11675 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11676 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11677 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11678 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11679 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11680 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11681 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11683 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11684 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11686 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11687 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11688 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11689 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11690 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11691 rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
11694 for (i = 0;i < texturenumsurfaces;i++)
11696 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11697 surfacenumvertices = texturesurfacelist[i]->num_vertices;
11698 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11699 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11700 // copy only the data requested
11701 if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
11702 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
11703 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11704 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11705 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11707 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11708 memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11709 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11710 memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11711 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11713 memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11714 memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11716 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11717 memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11718 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11719 memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11720 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11721 memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11723 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11724 numvertices += surfacenumvertices;
11725 numtriangles += surfacenumtriangles;
11728 // generate a 16bit index array as well if possible
11729 // (in general, dynamic batches fit)
11730 if (numvertices <= 65536)
11732 rsurface.batchelement3s = rsurface.array_batchelement3s;
11733 for (i = 0;i < numtriangles*3;i++)
11734 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11737 // since we've copied everything, the batch now starts at 0
11738 rsurface.batchfirstvertex = 0;
11739 rsurface.batchnumvertices = numvertices;
11740 rsurface.batchfirsttriangle = 0;
11741 rsurface.batchnumtriangles = numtriangles;
11744 // q1bsp surfaces rendered in vertex color mode have to have colors
11745 // calculated based on lightstyles
11746 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11748 // generate color arrays for the surfaces in this list
11752 const int *offsets;
11753 const unsigned char *lm;
11755 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11756 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11757 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11758 for (i = 0;i < texturenumsurfaces;i++)
11760 surface = texturesurfacelist[i];
11761 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11762 surfacenumvertices = surface->num_vertices;
11763 if (surface->lightmapinfo->samples)
11765 for (j = 0;j < surfacenumvertices;j++)
11767 lm = surface->lightmapinfo->samples + offsets[j];
11768 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11769 VectorScale(lm, scale, c);
11770 if (surface->lightmapinfo->styles[1] != 255)
11772 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11774 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11775 VectorMA(c, scale, lm, c);
11776 if (surface->lightmapinfo->styles[2] != 255)
11779 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11780 VectorMA(c, scale, lm, c);
11781 if (surface->lightmapinfo->styles[3] != 255)
11784 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11785 VectorMA(c, scale, lm, c);
11792 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);
11798 for (j = 0;j < surfacenumvertices;j++)
11800 Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11807 // if vertices are deformed (sprite flares and things in maps, possibly
11808 // water waves, bulges and other deformations), modify the copied vertices
11810 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11812 switch (deform->deform)
11815 case Q3DEFORM_PROJECTIONSHADOW:
11816 case Q3DEFORM_TEXT0:
11817 case Q3DEFORM_TEXT1:
11818 case Q3DEFORM_TEXT2:
11819 case Q3DEFORM_TEXT3:
11820 case Q3DEFORM_TEXT4:
11821 case Q3DEFORM_TEXT5:
11822 case Q3DEFORM_TEXT6:
11823 case Q3DEFORM_TEXT7:
11824 case Q3DEFORM_NONE:
11826 case Q3DEFORM_AUTOSPRITE:
11827 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11828 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11829 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11830 VectorNormalize(newforward);
11831 VectorNormalize(newright);
11832 VectorNormalize(newup);
11833 // a single autosprite surface can contain multiple sprites...
11834 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11836 VectorClear(center);
11837 for (i = 0;i < 4;i++)
11838 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11839 VectorScale(center, 0.25f, center);
11840 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11841 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11842 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11843 for (i = 0;i < 4;i++)
11845 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11846 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
11849 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11850 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11851 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);
11852 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11853 rsurface.batchvertex3f_vertexbuffer = NULL;
11854 rsurface.batchvertex3f_bufferoffset = 0;
11855 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11856 rsurface.batchsvector3f_vertexbuffer = NULL;
11857 rsurface.batchsvector3f_bufferoffset = 0;
11858 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11859 rsurface.batchtvector3f_vertexbuffer = NULL;
11860 rsurface.batchtvector3f_bufferoffset = 0;
11861 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11862 rsurface.batchnormal3f_vertexbuffer = NULL;
11863 rsurface.batchnormal3f_bufferoffset = 0;
11865 case Q3DEFORM_AUTOSPRITE2:
11866 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11867 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11868 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11869 VectorNormalize(newforward);
11870 VectorNormalize(newright);
11871 VectorNormalize(newup);
11873 const float *v1, *v2;
11883 memset(shortest, 0, sizeof(shortest));
11884 // a single autosprite surface can contain multiple sprites...
11885 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11887 VectorClear(center);
11888 for (i = 0;i < 4;i++)
11889 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11890 VectorScale(center, 0.25f, center);
11891 // find the two shortest edges, then use them to define the
11892 // axis vectors for rotating around the central axis
11893 for (i = 0;i < 6;i++)
11895 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11896 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11897 l = VectorDistance2(v1, v2);
11898 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11899 if (v1[2] != v2[2])
11900 l += (1.0f / 1024.0f);
11901 if (shortest[0].length2 > l || i == 0)
11903 shortest[1] = shortest[0];
11904 shortest[0].length2 = l;
11905 shortest[0].v1 = v1;
11906 shortest[0].v2 = v2;
11908 else if (shortest[1].length2 > l || i == 1)
11910 shortest[1].length2 = l;
11911 shortest[1].v1 = v1;
11912 shortest[1].v2 = v2;
11915 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11916 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11917 // this calculates the right vector from the shortest edge
11918 // and the up vector from the edge midpoints
11919 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11920 VectorNormalize(right);
11921 VectorSubtract(end, start, up);
11922 VectorNormalize(up);
11923 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11924 VectorSubtract(rsurface.localvieworigin, center, forward);
11925 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11926 VectorNegate(forward, forward);
11927 VectorReflect(forward, 0, up, forward);
11928 VectorNormalize(forward);
11929 CrossProduct(up, forward, newright);
11930 VectorNormalize(newright);
11931 // rotate the quad around the up axis vector, this is made
11932 // especially easy by the fact we know the quad is flat,
11933 // so we only have to subtract the center position and
11934 // measure distance along the right vector, and then
11935 // multiply that by the newright vector and add back the
11937 // we also need to subtract the old position to undo the
11938 // displacement from the center, which we do with a
11939 // DotProduct, the subtraction/addition of center is also
11940 // optimized into DotProducts here
11941 l = DotProduct(right, center);
11942 for (i = 0;i < 4;i++)
11944 v1 = rsurface.batchvertex3f + 3*(j+i);
11945 f = DotProduct(right, v1) - l;
11946 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
11950 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11951 rsurface.batchvertex3f_vertexbuffer = NULL;
11952 rsurface.batchvertex3f_bufferoffset = 0;
11953 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11955 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11956 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11957 rsurface.batchnormal3f_vertexbuffer = NULL;
11958 rsurface.batchnormal3f_bufferoffset = 0;
11960 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11962 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);
11963 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11964 rsurface.batchsvector3f_vertexbuffer = NULL;
11965 rsurface.batchsvector3f_bufferoffset = 0;
11966 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11967 rsurface.batchtvector3f_vertexbuffer = NULL;
11968 rsurface.batchtvector3f_bufferoffset = 0;
11971 case Q3DEFORM_NORMAL:
11972 // deform the normals to make reflections wavey
11973 for (j = 0;j < rsurface.batchnumvertices;j++)
11976 float *normal = rsurface.array_batchnormal3f + 3*j;
11977 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11978 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11979 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]);
11980 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]);
11981 VectorNormalize(normal);
11983 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11984 rsurface.batchnormal3f_vertexbuffer = NULL;
11985 rsurface.batchnormal3f_bufferoffset = 0;
11986 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11988 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);
11989 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11990 rsurface.batchsvector3f_vertexbuffer = NULL;
11991 rsurface.batchsvector3f_bufferoffset = 0;
11992 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11993 rsurface.batchtvector3f_vertexbuffer = NULL;
11994 rsurface.batchtvector3f_bufferoffset = 0;
11997 case Q3DEFORM_WAVE:
11998 // deform vertex array to make wavey water and flags and such
11999 waveparms[0] = deform->waveparms[0];
12000 waveparms[1] = deform->waveparms[1];
12001 waveparms[2] = deform->waveparms[2];
12002 waveparms[3] = deform->waveparms[3];
12003 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
12004 break; // if wavefunc is a nop, don't make a dynamic vertex array
12005 // this is how a divisor of vertex influence on deformation
12006 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
12007 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
12008 for (j = 0;j < rsurface.batchnumvertices;j++)
12010 // if the wavefunc depends on time, evaluate it per-vertex
12013 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
12014 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
12016 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
12018 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12019 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
12020 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12021 rsurface.batchvertex3f_vertexbuffer = NULL;
12022 rsurface.batchvertex3f_bufferoffset = 0;
12023 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
12024 rsurface.batchnormal3f_vertexbuffer = NULL;
12025 rsurface.batchnormal3f_bufferoffset = 0;
12026 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12028 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);
12029 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
12030 rsurface.batchsvector3f_vertexbuffer = NULL;
12031 rsurface.batchsvector3f_bufferoffset = 0;
12032 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
12033 rsurface.batchtvector3f_vertexbuffer = NULL;
12034 rsurface.batchtvector3f_bufferoffset = 0;
12037 case Q3DEFORM_BULGE:
12038 // deform vertex array to make the surface have moving bulges
12039 for (j = 0;j < rsurface.batchnumvertices;j++)
12041 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
12042 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
12044 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12045 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
12046 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12047 rsurface.batchvertex3f_vertexbuffer = NULL;
12048 rsurface.batchvertex3f_bufferoffset = 0;
12049 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
12050 rsurface.batchnormal3f_vertexbuffer = NULL;
12051 rsurface.batchnormal3f_bufferoffset = 0;
12052 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12054 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);
12055 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
12056 rsurface.batchsvector3f_vertexbuffer = NULL;
12057 rsurface.batchsvector3f_bufferoffset = 0;
12058 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
12059 rsurface.batchtvector3f_vertexbuffer = NULL;
12060 rsurface.batchtvector3f_bufferoffset = 0;
12063 case Q3DEFORM_MOVE:
12064 // deform vertex array
12065 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
12066 break; // if wavefunc is a nop, don't make a dynamic vertex array
12067 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
12068 VectorScale(deform->parms, scale, waveparms);
12069 for (j = 0;j < rsurface.batchnumvertices;j++)
12070 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
12071 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12072 rsurface.batchvertex3f_vertexbuffer = NULL;
12073 rsurface.batchvertex3f_bufferoffset = 0;
12078 // generate texcoords based on the chosen texcoord source
12079 switch(rsurface.texture->tcgen.tcgen)
12082 case Q3TCGEN_TEXTURE:
12084 case Q3TCGEN_LIGHTMAP:
12085 if (rsurface.batchtexcoordlightmap2f)
12086 memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
12087 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12088 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12089 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12091 case Q3TCGEN_VECTOR:
12092 for (j = 0;j < rsurface.batchnumvertices;j++)
12094 rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
12095 rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
12097 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12098 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12099 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12101 case Q3TCGEN_ENVIRONMENT:
12102 // make environment reflections using a spheremap
12103 for (j = 0;j < rsurface.batchnumvertices;j++)
12105 // identical to Q3A's method, but executed in worldspace so
12106 // carried models can be shiny too
12108 float viewer[3], d, reflected[3], worldreflected[3];
12110 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
12111 // VectorNormalize(viewer);
12113 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
12115 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
12116 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
12117 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
12118 // note: this is proportinal to viewer, so we can normalize later
12120 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
12121 VectorNormalize(worldreflected);
12123 // note: this sphere map only uses world x and z!
12124 // so positive and negative y will LOOK THE SAME.
12125 rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
12126 rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
12128 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12129 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12130 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12133 // the only tcmod that needs software vertex processing is turbulent, so
12134 // check for it here and apply the changes if needed
12135 // and we only support that as the first one
12136 // (handling a mixture of turbulent and other tcmods would be problematic
12137 // without punting it entirely to a software path)
12138 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
12140 amplitude = rsurface.texture->tcmods[0].parms[1];
12141 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
12142 for (j = 0;j < rsurface.batchnumvertices;j++)
12144 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);
12145 rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12147 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12148 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12149 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12152 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
12154 // convert the modified arrays to vertex structs
12155 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
12156 rsurface.batchvertexmeshbuffer = NULL;
12157 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
12158 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12159 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
12160 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
12161 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12162 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
12163 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
12165 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12167 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
12168 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
12171 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
12172 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12173 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
12174 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
12175 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12176 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
12177 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
12178 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12179 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
12182 if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
12184 // convert the modified arrays to vertex structs
12185 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
12186 rsurface.batchvertexpositionbuffer = NULL;
12187 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
12188 memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
12190 for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
12191 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
12195 void RSurf_DrawBatch(void)
12197 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);
12200 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
12202 // pick the closest matching water plane
12203 int planeindex, vertexindex, bestplaneindex = -1;
12207 r_waterstate_waterplane_t *p;
12209 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
12211 if(p->camera_entity != rsurface.texture->camera_entity)
12214 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
12215 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
12217 Matrix4x4_Transform(&rsurface.matrix, v, vert);
12218 d += fabs(PlaneDiff(vert, &p->plane));
12220 if (bestd > d || bestplaneindex < 0)
12223 bestplaneindex = planeindex;
12226 return bestplaneindex;
12229 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
12232 for (i = 0;i < rsurface.batchnumvertices;i++)
12233 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
12234 rsurface.passcolor4f = rsurface.array_passcolor4f;
12235 rsurface.passcolor4f_vertexbuffer = 0;
12236 rsurface.passcolor4f_bufferoffset = 0;
12239 static void RSurf_DrawBatch_GL11_ApplyFog(void)
12246 if (rsurface.passcolor4f)
12248 // generate color arrays
12249 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)
12251 f = RSurf_FogVertex(v);
12260 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
12262 f = RSurf_FogVertex(v);
12269 rsurface.passcolor4f = rsurface.array_passcolor4f;
12270 rsurface.passcolor4f_vertexbuffer = 0;
12271 rsurface.passcolor4f_bufferoffset = 0;
12274 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
12281 if (!rsurface.passcolor4f)
12283 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)
12285 f = RSurf_FogVertex(v);
12286 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
12287 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
12288 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
12291 rsurface.passcolor4f = rsurface.array_passcolor4f;
12292 rsurface.passcolor4f_vertexbuffer = 0;
12293 rsurface.passcolor4f_bufferoffset = 0;
12296 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
12301 if (!rsurface.passcolor4f)
12303 for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12310 rsurface.passcolor4f = rsurface.array_passcolor4f;
12311 rsurface.passcolor4f_vertexbuffer = 0;
12312 rsurface.passcolor4f_bufferoffset = 0;
12315 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12320 if (!rsurface.passcolor4f)
12322 for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12324 c2[0] = c[0] + r_refdef.scene.ambient;
12325 c2[1] = c[1] + r_refdef.scene.ambient;
12326 c2[2] = c[2] + r_refdef.scene.ambient;
12329 rsurface.passcolor4f = rsurface.array_passcolor4f;
12330 rsurface.passcolor4f_vertexbuffer = 0;
12331 rsurface.passcolor4f_bufferoffset = 0;
12334 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12337 rsurface.passcolor4f = NULL;
12338 rsurface.passcolor4f_vertexbuffer = 0;
12339 rsurface.passcolor4f_bufferoffset = 0;
12340 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12341 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12342 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12343 GL_Color(r, g, b, a);
12344 R_Mesh_TexBind(0, rsurface.lightmaptexture);
12348 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12350 // TODO: optimize applyfog && applycolor case
12351 // just apply fog if necessary, and tint the fog color array if necessary
12352 rsurface.passcolor4f = NULL;
12353 rsurface.passcolor4f_vertexbuffer = 0;
12354 rsurface.passcolor4f_bufferoffset = 0;
12355 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12356 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12357 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12358 GL_Color(r, g, b, a);
12362 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12365 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12366 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12367 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12368 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12369 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12370 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12371 GL_Color(r, g, b, a);
12375 static void RSurf_DrawBatch_GL11_ClampColor(void)
12380 if (!rsurface.passcolor4f)
12382 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12384 c2[0] = bound(0.0f, c1[0], 1.0f);
12385 c2[1] = bound(0.0f, c1[1], 1.0f);
12386 c2[2] = bound(0.0f, c1[2], 1.0f);
12387 c2[3] = bound(0.0f, c1[3], 1.0f);
12391 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
12401 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)
12403 f = -DotProduct(r_refdef.view.forward, n);
12405 f = f * 0.85 + 0.15; // work around so stuff won't get black
12406 f *= r_refdef.lightmapintensity;
12407 Vector4Set(c, f, f, f, 1);
12410 rsurface.passcolor4f = rsurface.array_passcolor4f;
12411 rsurface.passcolor4f_vertexbuffer = 0;
12412 rsurface.passcolor4f_bufferoffset = 0;
12415 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12417 RSurf_DrawBatch_GL11_ApplyFakeLight();
12418 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12419 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12420 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12421 GL_Color(r, g, b, a);
12425 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12433 vec3_t ambientcolor;
12434 vec3_t diffusecolor;
12438 VectorCopy(rsurface.modellight_lightdir, lightdir);
12439 f = 0.5f * r_refdef.lightmapintensity;
12440 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12441 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12442 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12443 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12444 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12445 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12447 if (VectorLength2(diffusecolor) > 0)
12449 // q3-style directional shading
12450 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)
12452 if ((f = DotProduct(n, lightdir)) > 0)
12453 VectorMA(ambientcolor, f, diffusecolor, c);
12455 VectorCopy(ambientcolor, c);
12462 rsurface.passcolor4f = rsurface.array_passcolor4f;
12463 rsurface.passcolor4f_vertexbuffer = 0;
12464 rsurface.passcolor4f_bufferoffset = 0;
12465 *applycolor = false;
12469 *r = ambientcolor[0];
12470 *g = ambientcolor[1];
12471 *b = ambientcolor[2];
12472 rsurface.passcolor4f = NULL;
12473 rsurface.passcolor4f_vertexbuffer = 0;
12474 rsurface.passcolor4f_bufferoffset = 0;
12478 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12480 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12481 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12482 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12483 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12484 GL_Color(r, g, b, a);
12488 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12494 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12496 f = 1 - RSurf_FogVertex(v);
12504 void RSurf_SetupDepthAndCulling(void)
12506 // submodels are biased to avoid z-fighting with world surfaces that they
12507 // may be exactly overlapping (avoids z-fighting artifacts on certain
12508 // doors and things in Quake maps)
12509 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12510 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12511 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12512 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12515 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12517 // transparent sky would be ridiculous
12518 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12520 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12521 skyrenderlater = true;
12522 RSurf_SetupDepthAndCulling();
12523 GL_DepthMask(true);
12524 // LordHavoc: HalfLife maps have freaky skypolys so don't use
12525 // skymasking on them, and Quake3 never did sky masking (unlike
12526 // software Quake and software Quake2), so disable the sky masking
12527 // in Quake3 maps as it causes problems with q3map2 sky tricks,
12528 // and skymasking also looks very bad when noclipping outside the
12529 // level, so don't use it then either.
12530 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12532 R_Mesh_ResetTextureState();
12533 if (skyrendermasked)
12535 R_SetupShader_DepthOrShadow();
12536 // depth-only (masking)
12537 GL_ColorMask(0,0,0,0);
12538 // just to make sure that braindead drivers don't draw
12539 // anything despite that colormask...
12540 GL_BlendFunc(GL_ZERO, GL_ONE);
12541 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12542 R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12546 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12548 GL_BlendFunc(GL_ONE, GL_ZERO);
12549 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12550 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12551 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12554 if (skyrendermasked)
12555 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12557 R_Mesh_ResetTextureState();
12558 GL_Color(1, 1, 1, 1);
12561 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12562 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12563 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12565 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12569 // render screenspace normalmap to texture
12570 GL_DepthMask(true);
12571 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12576 // bind lightmap texture
12578 // water/refraction/reflection/camera surfaces have to be handled specially
12579 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)) && !r_waterstate.renderingscene)
12581 int start, end, startplaneindex;
12582 for (start = 0;start < texturenumsurfaces;start = end)
12584 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12585 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12587 // now that we have a batch using the same planeindex, render it
12588 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
12590 // render water or distortion background
12591 GL_DepthMask(true);
12592 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));
12594 // blend surface on top
12595 GL_DepthMask(false);
12596 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12599 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) && !r_waterstate.renderingscene)
12601 // render surface with reflection texture as input
12602 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12603 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));
12610 // render surface batch normally
12611 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12612 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12616 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12618 // OpenGL 1.3 path - anything not completely ancient
12619 qboolean applycolor;
12622 const texturelayer_t *layer;
12623 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);
12624 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12626 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12629 int layertexrgbscale;
12630 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12632 if (layerindex == 0)
12633 GL_AlphaTest(true);
12636 GL_AlphaTest(false);
12637 GL_DepthFunc(GL_EQUAL);
12640 GL_DepthMask(layer->depthmask && writedepth);
12641 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12642 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12644 layertexrgbscale = 4;
12645 VectorScale(layer->color, 0.25f, layercolor);
12647 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12649 layertexrgbscale = 2;
12650 VectorScale(layer->color, 0.5f, layercolor);
12654 layertexrgbscale = 1;
12655 VectorScale(layer->color, 1.0f, layercolor);
12657 layercolor[3] = layer->color[3];
12658 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12659 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12660 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12661 switch (layer->type)
12663 case TEXTURELAYERTYPE_LITTEXTURE:
12664 // single-pass lightmapped texture with 2x rgbscale
12665 R_Mesh_TexBind(0, r_texture_white);
12666 R_Mesh_TexMatrix(0, NULL);
12667 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12668 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12669 R_Mesh_TexBind(1, layer->texture);
12670 R_Mesh_TexMatrix(1, &layer->texmatrix);
12671 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12672 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12673 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12674 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12675 else if (FAKELIGHT_ENABLED)
12676 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12677 else if (rsurface.uselightmaptexture)
12678 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12680 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12682 case TEXTURELAYERTYPE_TEXTURE:
12683 // singletexture unlit texture with transparency support
12684 R_Mesh_TexBind(0, layer->texture);
12685 R_Mesh_TexMatrix(0, &layer->texmatrix);
12686 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12687 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12688 R_Mesh_TexBind(1, 0);
12689 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12690 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12692 case TEXTURELAYERTYPE_FOG:
12693 // singletexture fogging
12694 if (layer->texture)
12696 R_Mesh_TexBind(0, layer->texture);
12697 R_Mesh_TexMatrix(0, &layer->texmatrix);
12698 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12699 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12703 R_Mesh_TexBind(0, 0);
12704 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12706 R_Mesh_TexBind(1, 0);
12707 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12708 // generate a color array for the fog pass
12709 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12710 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12714 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12717 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12719 GL_DepthFunc(GL_LEQUAL);
12720 GL_AlphaTest(false);
12724 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12726 // OpenGL 1.1 - crusty old voodoo path
12729 const texturelayer_t *layer;
12730 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);
12731 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12733 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12735 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12737 if (layerindex == 0)
12738 GL_AlphaTest(true);
12741 GL_AlphaTest(false);
12742 GL_DepthFunc(GL_EQUAL);
12745 GL_DepthMask(layer->depthmask && writedepth);
12746 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12747 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12748 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12749 switch (layer->type)
12751 case TEXTURELAYERTYPE_LITTEXTURE:
12752 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12754 // two-pass lit texture with 2x rgbscale
12755 // first the lightmap pass
12756 R_Mesh_TexBind(0, r_texture_white);
12757 R_Mesh_TexMatrix(0, NULL);
12758 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12759 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12760 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12761 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12762 else if (FAKELIGHT_ENABLED)
12763 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12764 else if (rsurface.uselightmaptexture)
12765 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12767 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12768 // then apply the texture to it
12769 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12770 R_Mesh_TexBind(0, layer->texture);
12771 R_Mesh_TexMatrix(0, &layer->texmatrix);
12772 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12773 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12774 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);
12778 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12779 R_Mesh_TexBind(0, layer->texture);
12780 R_Mesh_TexMatrix(0, &layer->texmatrix);
12781 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12782 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12783 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12784 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);
12786 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);
12789 case TEXTURELAYERTYPE_TEXTURE:
12790 // singletexture unlit texture with transparency support
12791 R_Mesh_TexBind(0, layer->texture);
12792 R_Mesh_TexMatrix(0, &layer->texmatrix);
12793 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12794 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12795 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);
12797 case TEXTURELAYERTYPE_FOG:
12798 // singletexture fogging
12799 if (layer->texture)
12801 R_Mesh_TexBind(0, layer->texture);
12802 R_Mesh_TexMatrix(0, &layer->texmatrix);
12803 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12804 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12808 R_Mesh_TexBind(0, 0);
12809 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12811 // generate a color array for the fog pass
12812 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12813 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12817 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12820 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12822 GL_DepthFunc(GL_LEQUAL);
12823 GL_AlphaTest(false);
12827 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12831 r_vertexgeneric_t *batchvertex;
12834 GL_AlphaTest(false);
12835 R_Mesh_ResetTextureState();
12836 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12838 if(rsurface.texture && rsurface.texture->currentskinframe)
12840 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12841 c[3] *= rsurface.texture->currentalpha;
12851 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12853 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12854 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12855 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12858 // brighten it up (as texture value 127 means "unlit")
12859 c[0] *= 2 * r_refdef.view.colorscale;
12860 c[1] *= 2 * r_refdef.view.colorscale;
12861 c[2] *= 2 * r_refdef.view.colorscale;
12863 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12864 c[3] *= r_wateralpha.value;
12866 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12868 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12869 GL_DepthMask(false);
12871 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12873 GL_BlendFunc(GL_ONE, GL_ONE);
12874 GL_DepthMask(false);
12876 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12878 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12879 GL_DepthMask(false);
12881 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12883 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12884 GL_DepthMask(false);
12888 GL_BlendFunc(GL_ONE, GL_ZERO);
12889 GL_DepthMask(writedepth);
12892 if (r_showsurfaces.integer == 3)
12894 rsurface.passcolor4f = NULL;
12896 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12898 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12900 rsurface.passcolor4f = NULL;
12901 rsurface.passcolor4f_vertexbuffer = 0;
12902 rsurface.passcolor4f_bufferoffset = 0;
12904 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12906 qboolean applycolor = true;
12909 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12911 r_refdef.lightmapintensity = 1;
12912 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12913 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12915 else if (FAKELIGHT_ENABLED)
12917 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12919 r_refdef.lightmapintensity = r_fakelight_intensity.value;
12920 RSurf_DrawBatch_GL11_ApplyFakeLight();
12921 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12925 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12927 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12928 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12929 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12932 if(!rsurface.passcolor4f)
12933 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12935 RSurf_DrawBatch_GL11_ApplyAmbient();
12936 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12937 if(r_refdef.fogenabled)
12938 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12939 RSurf_DrawBatch_GL11_ClampColor();
12941 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12942 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12945 else if (!r_refdef.view.showdebug)
12947 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12948 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12949 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12951 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12952 Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12954 R_Mesh_PrepareVertices_Generic_Unlock();
12957 else if (r_showsurfaces.integer == 4)
12959 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12960 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12961 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12963 unsigned char c = vi << 3;
12964 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12965 Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12967 R_Mesh_PrepareVertices_Generic_Unlock();
12970 else if (r_showsurfaces.integer == 2)
12973 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12974 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12975 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12977 unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12978 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12979 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12980 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12981 Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12982 Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12983 Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12985 R_Mesh_PrepareVertices_Generic_Unlock();
12986 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12990 int texturesurfaceindex;
12992 const msurface_t *surface;
12993 unsigned char surfacecolor4ub[4];
12994 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12995 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12997 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12999 surface = texturesurfacelist[texturesurfaceindex];
13000 k = (int)(((size_t)surface) / sizeof(msurface_t));
13001 Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
13002 for (j = 0;j < surface->num_vertices;j++)
13004 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13005 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
13009 R_Mesh_PrepareVertices_Generic_Unlock();
13014 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13017 RSurf_SetupDepthAndCulling();
13018 if (r_showsurfaces.integer)
13020 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13023 switch (vid.renderpath)
13025 case RENDERPATH_GL20:
13026 case RENDERPATH_CGGL:
13027 case RENDERPATH_D3D9:
13028 case RENDERPATH_D3D10:
13029 case RENDERPATH_D3D11:
13030 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13032 case RENDERPATH_GL13:
13033 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13035 case RENDERPATH_GL11:
13036 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13042 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13045 RSurf_SetupDepthAndCulling();
13046 if (r_showsurfaces.integer)
13048 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13051 switch (vid.renderpath)
13053 case RENDERPATH_GL20:
13054 case RENDERPATH_CGGL:
13055 case RENDERPATH_D3D9:
13056 case RENDERPATH_D3D10:
13057 case RENDERPATH_D3D11:
13058 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13060 case RENDERPATH_GL13:
13061 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13063 case RENDERPATH_GL11:
13064 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13070 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13073 int texturenumsurfaces, endsurface;
13074 texture_t *texture;
13075 const msurface_t *surface;
13076 #define MAXBATCH_TRANSPARENTSURFACES 256
13077 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
13079 // if the model is static it doesn't matter what value we give for
13080 // wantnormals and wanttangents, so this logic uses only rules applicable
13081 // to a model, knowing that they are meaningless otherwise
13082 if (ent == r_refdef.scene.worldentity)
13083 RSurf_ActiveWorldEntity();
13084 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13085 RSurf_ActiveModelEntity(ent, false, false, false);
13088 switch (vid.renderpath)
13090 case RENDERPATH_GL20:
13091 case RENDERPATH_CGGL:
13092 case RENDERPATH_D3D9:
13093 case RENDERPATH_D3D10:
13094 case RENDERPATH_D3D11:
13095 RSurf_ActiveModelEntity(ent, true, true, false);
13097 case RENDERPATH_GL13:
13098 case RENDERPATH_GL11:
13099 RSurf_ActiveModelEntity(ent, true, false, false);
13104 if (r_transparentdepthmasking.integer)
13106 qboolean setup = false;
13107 for (i = 0;i < numsurfaces;i = j)
13110 surface = rsurface.modelsurfaces + surfacelist[i];
13111 texture = surface->texture;
13112 rsurface.texture = R_GetCurrentTexture(texture);
13113 rsurface.lightmaptexture = NULL;
13114 rsurface.deluxemaptexture = NULL;
13115 rsurface.uselightmaptexture = false;
13116 // scan ahead until we find a different texture
13117 endsurface = min(i + 1024, numsurfaces);
13118 texturenumsurfaces = 0;
13119 texturesurfacelist[texturenumsurfaces++] = surface;
13120 for (;j < endsurface;j++)
13122 surface = rsurface.modelsurfaces + surfacelist[j];
13123 if (texture != surface->texture)
13125 texturesurfacelist[texturenumsurfaces++] = surface;
13127 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
13129 // render the range of surfaces as depth
13133 GL_ColorMask(0,0,0,0);
13135 GL_DepthTest(true);
13136 GL_BlendFunc(GL_ONE, GL_ZERO);
13137 GL_DepthMask(true);
13138 GL_AlphaTest(false);
13139 R_Mesh_ResetTextureState();
13140 R_SetupShader_DepthOrShadow();
13142 RSurf_SetupDepthAndCulling();
13143 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13144 R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13148 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
13151 for (i = 0;i < numsurfaces;i = j)
13154 surface = rsurface.modelsurfaces + surfacelist[i];
13155 texture = surface->texture;
13156 rsurface.texture = R_GetCurrentTexture(texture);
13157 // scan ahead until we find a different texture
13158 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
13159 texturenumsurfaces = 0;
13160 texturesurfacelist[texturenumsurfaces++] = surface;
13161 if(FAKELIGHT_ENABLED)
13163 rsurface.lightmaptexture = NULL;
13164 rsurface.deluxemaptexture = NULL;
13165 rsurface.uselightmaptexture = false;
13166 for (;j < endsurface;j++)
13168 surface = rsurface.modelsurfaces + surfacelist[j];
13169 if (texture != surface->texture)
13171 texturesurfacelist[texturenumsurfaces++] = surface;
13176 rsurface.lightmaptexture = surface->lightmaptexture;
13177 rsurface.deluxemaptexture = surface->deluxemaptexture;
13178 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
13179 for (;j < endsurface;j++)
13181 surface = rsurface.modelsurfaces + surfacelist[j];
13182 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
13184 texturesurfacelist[texturenumsurfaces++] = surface;
13187 // render the range of surfaces
13188 if (ent == r_refdef.scene.worldentity)
13189 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13191 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13193 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13194 GL_AlphaTest(false);
13197 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
13199 // transparent surfaces get pushed off into the transparent queue
13200 int surfacelistindex;
13201 const msurface_t *surface;
13202 vec3_t tempcenter, center;
13203 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
13205 surface = texturesurfacelist[surfacelistindex];
13206 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
13207 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
13208 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
13209 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
13210 if (queueentity->transparent_offset) // transparent offset
13212 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
13213 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
13214 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
13216 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
13220 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
13222 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
13224 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
13226 RSurf_SetupDepthAndCulling();
13227 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13228 R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13232 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
13234 const entity_render_t *queueentity = r_refdef.scene.worldentity;
13237 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13240 if (!rsurface.texture->currentnumlayers)
13242 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13243 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13245 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13247 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13248 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13249 else if (!rsurface.texture->currentnumlayers)
13251 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13253 // in the deferred case, transparent surfaces were queued during prepass
13254 if (!r_shadow_usingdeferredprepass)
13255 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13259 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13260 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13265 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13268 texture_t *texture;
13269 // break the surface list down into batches by texture and use of lightmapping
13270 for (i = 0;i < numsurfaces;i = j)
13273 // texture is the base texture pointer, rsurface.texture is the
13274 // current frame/skin the texture is directing us to use (for example
13275 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13276 // use skin 1 instead)
13277 texture = surfacelist[i]->texture;
13278 rsurface.texture = R_GetCurrentTexture(texture);
13279 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13281 // if this texture is not the kind we want, skip ahead to the next one
13282 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13286 if(FAKELIGHT_ENABLED || depthonly || prepass)
13288 rsurface.lightmaptexture = NULL;
13289 rsurface.deluxemaptexture = NULL;
13290 rsurface.uselightmaptexture = false;
13291 // simply scan ahead until we find a different texture or lightmap state
13292 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13297 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13298 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13299 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13300 // simply scan ahead until we find a different texture or lightmap state
13301 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13304 // render the range of surfaces
13305 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
13309 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
13313 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13316 if (!rsurface.texture->currentnumlayers)
13318 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13319 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13321 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13323 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13324 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13325 else if (!rsurface.texture->currentnumlayers)
13327 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13329 // in the deferred case, transparent surfaces were queued during prepass
13330 if (!r_shadow_usingdeferredprepass)
13331 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13335 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13336 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13341 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13344 texture_t *texture;
13345 // break the surface list down into batches by texture and use of lightmapping
13346 for (i = 0;i < numsurfaces;i = j)
13349 // texture is the base texture pointer, rsurface.texture is the
13350 // current frame/skin the texture is directing us to use (for example
13351 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13352 // use skin 1 instead)
13353 texture = surfacelist[i]->texture;
13354 rsurface.texture = R_GetCurrentTexture(texture);
13355 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13357 // if this texture is not the kind we want, skip ahead to the next one
13358 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13362 if(FAKELIGHT_ENABLED || depthonly || prepass)
13364 rsurface.lightmaptexture = NULL;
13365 rsurface.deluxemaptexture = NULL;
13366 rsurface.uselightmaptexture = false;
13367 // simply scan ahead until we find a different texture or lightmap state
13368 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13373 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13374 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13375 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13376 // simply scan ahead until we find a different texture or lightmap state
13377 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13380 // render the range of surfaces
13381 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
13385 float locboxvertex3f[6*4*3] =
13387 1,0,1, 1,0,0, 1,1,0, 1,1,1,
13388 0,1,1, 0,1,0, 0,0,0, 0,0,1,
13389 1,1,1, 1,1,0, 0,1,0, 0,1,1,
13390 0,0,1, 0,0,0, 1,0,0, 1,0,1,
13391 0,0,1, 1,0,1, 1,1,1, 0,1,1,
13392 1,0,0, 0,0,0, 0,1,0, 1,1,0
13395 unsigned short locboxelements[6*2*3] =
13400 12,13,14, 12,14,15,
13401 16,17,18, 16,18,19,
13405 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13408 cl_locnode_t *loc = (cl_locnode_t *)ent;
13410 float vertex3f[6*4*3];
13412 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13413 GL_DepthMask(false);
13414 GL_DepthRange(0, 1);
13415 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13416 GL_DepthTest(true);
13417 GL_CullFace(GL_NONE);
13418 R_EntityMatrix(&identitymatrix);
13420 R_Mesh_ResetTextureState();
13422 i = surfacelist[0];
13423 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13424 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13425 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13426 surfacelist[0] < 0 ? 0.5f : 0.125f);
13428 if (VectorCompare(loc->mins, loc->maxs))
13430 VectorSet(size, 2, 2, 2);
13431 VectorMA(loc->mins, -0.5f, size, mins);
13435 VectorCopy(loc->mins, mins);
13436 VectorSubtract(loc->maxs, loc->mins, size);
13439 for (i = 0;i < 6*4*3;)
13440 for (j = 0;j < 3;j++, i++)
13441 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13443 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13444 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13445 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13448 void R_DrawLocs(void)
13451 cl_locnode_t *loc, *nearestloc;
13453 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13454 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13456 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13457 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13461 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13463 if (decalsystem->decals)
13464 Mem_Free(decalsystem->decals);
13465 memset(decalsystem, 0, sizeof(*decalsystem));
13468 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)
13471 tridecal_t *decals;
13474 // expand or initialize the system
13475 if (decalsystem->maxdecals <= decalsystem->numdecals)
13477 decalsystem_t old = *decalsystem;
13478 qboolean useshortelements;
13479 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13480 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13481 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)));
13482 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13483 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13484 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13485 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13486 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13487 if (decalsystem->numdecals)
13488 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13490 Mem_Free(old.decals);
13491 for (i = 0;i < decalsystem->maxdecals*3;i++)
13492 decalsystem->element3i[i] = i;
13493 if (useshortelements)
13494 for (i = 0;i < decalsystem->maxdecals*3;i++)
13495 decalsystem->element3s[i] = i;
13498 // grab a decal and search for another free slot for the next one
13499 decals = decalsystem->decals;
13500 decal = decalsystem->decals + (i = decalsystem->freedecal++);
13501 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13503 decalsystem->freedecal = i;
13504 if (decalsystem->numdecals <= i)
13505 decalsystem->numdecals = i + 1;
13507 // initialize the decal
13509 decal->triangleindex = triangleindex;
13510 decal->surfaceindex = surfaceindex;
13511 decal->decalsequence = decalsequence;
13512 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13513 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13514 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13515 decal->color4ub[0][3] = 255;
13516 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13517 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13518 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13519 decal->color4ub[1][3] = 255;
13520 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13521 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13522 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13523 decal->color4ub[2][3] = 255;
13524 decal->vertex3f[0][0] = v0[0];
13525 decal->vertex3f[0][1] = v0[1];
13526 decal->vertex3f[0][2] = v0[2];
13527 decal->vertex3f[1][0] = v1[0];
13528 decal->vertex3f[1][1] = v1[1];
13529 decal->vertex3f[1][2] = v1[2];
13530 decal->vertex3f[2][0] = v2[0];
13531 decal->vertex3f[2][1] = v2[1];
13532 decal->vertex3f[2][2] = v2[2];
13533 decal->texcoord2f[0][0] = t0[0];
13534 decal->texcoord2f[0][1] = t0[1];
13535 decal->texcoord2f[1][0] = t1[0];
13536 decal->texcoord2f[1][1] = t1[1];
13537 decal->texcoord2f[2][0] = t2[0];
13538 decal->texcoord2f[2][1] = t2[1];
13541 extern cvar_t cl_decals_bias;
13542 extern cvar_t cl_decals_models;
13543 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13544 // baseparms, parms, temps
13545 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)
13550 const float *vertex3f;
13552 float points[2][9][3];
13559 e = rsurface.modelelement3i + 3*triangleindex;
13561 vertex3f = rsurface.modelvertex3f;
13563 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13565 index = 3*e[cornerindex];
13566 VectorCopy(vertex3f + index, v[cornerindex]);
13569 //TriangleNormal(v[0], v[1], v[2], normal);
13570 //if (DotProduct(normal, localnormal) < 0.0f)
13572 // clip by each of the box planes formed from the projection matrix
13573 // if anything survives, we emit the decal
13574 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]);
13577 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]);
13580 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]);
13583 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]);
13586 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]);
13589 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]);
13592 // some part of the triangle survived, so we have to accept it...
13595 // dynamic always uses the original triangle
13597 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13599 index = 3*e[cornerindex];
13600 VectorCopy(vertex3f + index, v[cornerindex]);
13603 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13605 // convert vertex positions to texcoords
13606 Matrix4x4_Transform(projection, v[cornerindex], temp);
13607 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13608 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13609 // calculate distance fade from the projection origin
13610 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13611 f = bound(0.0f, f, 1.0f);
13612 c[cornerindex][0] = r * f;
13613 c[cornerindex][1] = g * f;
13614 c[cornerindex][2] = b * f;
13615 c[cornerindex][3] = 1.0f;
13616 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13619 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);
13621 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13622 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);
13624 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)
13626 matrix4x4_t projection;
13627 decalsystem_t *decalsystem;
13630 const msurface_t *surface;
13631 const msurface_t *surfaces;
13632 const int *surfacelist;
13633 const texture_t *texture;
13635 int numsurfacelist;
13636 int surfacelistindex;
13639 float localorigin[3];
13640 float localnormal[3];
13641 float localmins[3];
13642 float localmaxs[3];
13645 float planes[6][4];
13648 int bih_triangles_count;
13649 int bih_triangles[256];
13650 int bih_surfaces[256];
13652 decalsystem = &ent->decalsystem;
13653 model = ent->model;
13654 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13656 R_DecalSystem_Reset(&ent->decalsystem);
13660 if (!model->brush.data_leafs && !cl_decals_models.integer)
13662 if (decalsystem->model)
13663 R_DecalSystem_Reset(decalsystem);
13667 if (decalsystem->model != model)
13668 R_DecalSystem_Reset(decalsystem);
13669 decalsystem->model = model;
13671 RSurf_ActiveModelEntity(ent, false, false, false);
13673 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13674 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13675 VectorNormalize(localnormal);
13676 localsize = worldsize*rsurface.inversematrixscale;
13677 localmins[0] = localorigin[0] - localsize;
13678 localmins[1] = localorigin[1] - localsize;
13679 localmins[2] = localorigin[2] - localsize;
13680 localmaxs[0] = localorigin[0] + localsize;
13681 localmaxs[1] = localorigin[1] + localsize;
13682 localmaxs[2] = localorigin[2] + localsize;
13684 //VectorCopy(localnormal, planes[4]);
13685 //VectorVectors(planes[4], planes[2], planes[0]);
13686 AnglesFromVectors(angles, localnormal, NULL, false);
13687 AngleVectors(angles, planes[0], planes[2], planes[4]);
13688 VectorNegate(planes[0], planes[1]);
13689 VectorNegate(planes[2], planes[3]);
13690 VectorNegate(planes[4], planes[5]);
13691 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13692 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13693 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13694 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13695 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13696 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13701 matrix4x4_t forwardprojection;
13702 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13703 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13708 float projectionvector[4][3];
13709 VectorScale(planes[0], ilocalsize, projectionvector[0]);
13710 VectorScale(planes[2], ilocalsize, projectionvector[1]);
13711 VectorScale(planes[4], ilocalsize, projectionvector[2]);
13712 projectionvector[0][0] = planes[0][0] * ilocalsize;
13713 projectionvector[0][1] = planes[1][0] * ilocalsize;
13714 projectionvector[0][2] = planes[2][0] * ilocalsize;
13715 projectionvector[1][0] = planes[0][1] * ilocalsize;
13716 projectionvector[1][1] = planes[1][1] * ilocalsize;
13717 projectionvector[1][2] = planes[2][1] * ilocalsize;
13718 projectionvector[2][0] = planes[0][2] * ilocalsize;
13719 projectionvector[2][1] = planes[1][2] * ilocalsize;
13720 projectionvector[2][2] = planes[2][2] * ilocalsize;
13721 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13722 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13723 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13724 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13728 dynamic = model->surfmesh.isanimated;
13729 numsurfacelist = model->nummodelsurfaces;
13730 surfacelist = model->sortedmodelsurfaces;
13731 surfaces = model->data_surfaces;
13734 bih_triangles_count = -1;
13737 if(model->render_bih.numleafs)
13738 bih = &model->render_bih;
13739 else if(model->collision_bih.numleafs)
13740 bih = &model->collision_bih;
13743 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13744 if(bih_triangles_count == 0)
13746 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13748 if(bih_triangles_count > 0)
13750 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13752 surfaceindex = bih_surfaces[triangleindex];
13753 surface = surfaces + surfaceindex;
13754 texture = surface->texture;
13755 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13757 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13759 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13764 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13766 surfaceindex = surfacelist[surfacelistindex];
13767 surface = surfaces + surfaceindex;
13768 // check cull box first because it rejects more than any other check
13769 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13771 // skip transparent surfaces
13772 texture = surface->texture;
13773 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13775 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13777 numtriangles = surface->num_triangles;
13778 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13779 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13784 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13785 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)
13787 int renderentityindex;
13788 float worldmins[3];
13789 float worldmaxs[3];
13790 entity_render_t *ent;
13792 if (!cl_decals_newsystem.integer)
13795 worldmins[0] = worldorigin[0] - worldsize;
13796 worldmins[1] = worldorigin[1] - worldsize;
13797 worldmins[2] = worldorigin[2] - worldsize;
13798 worldmaxs[0] = worldorigin[0] + worldsize;
13799 worldmaxs[1] = worldorigin[1] + worldsize;
13800 worldmaxs[2] = worldorigin[2] + worldsize;
13802 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13804 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13806 ent = r_refdef.scene.entities[renderentityindex];
13807 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13810 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13814 typedef struct r_decalsystem_splatqueue_s
13816 vec3_t worldorigin;
13817 vec3_t worldnormal;
13823 r_decalsystem_splatqueue_t;
13825 int r_decalsystem_numqueued = 0;
13826 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13828 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)
13830 r_decalsystem_splatqueue_t *queue;
13832 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13835 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13836 VectorCopy(worldorigin, queue->worldorigin);
13837 VectorCopy(worldnormal, queue->worldnormal);
13838 Vector4Set(queue->color, r, g, b, a);
13839 Vector4Set(queue->tcrange, s1, t1, s2, t2);
13840 queue->worldsize = worldsize;
13841 queue->decalsequence = cl.decalsequence++;
13844 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13847 r_decalsystem_splatqueue_t *queue;
13849 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13850 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);
13851 r_decalsystem_numqueued = 0;
13854 extern cvar_t cl_decals_max;
13855 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13858 decalsystem_t *decalsystem = &ent->decalsystem;
13865 if (!decalsystem->numdecals)
13868 if (r_showsurfaces.integer)
13871 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13873 R_DecalSystem_Reset(decalsystem);
13877 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13878 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13880 if (decalsystem->lastupdatetime)
13881 frametime = (cl.time - decalsystem->lastupdatetime);
13884 decalsystem->lastupdatetime = cl.time;
13885 decal = decalsystem->decals;
13886 numdecals = decalsystem->numdecals;
13888 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13890 if (decal->color4ub[0][3])
13892 decal->lived += frametime;
13893 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13895 memset(decal, 0, sizeof(*decal));
13896 if (decalsystem->freedecal > i)
13897 decalsystem->freedecal = i;
13901 decal = decalsystem->decals;
13902 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13905 // collapse the array by shuffling the tail decals into the gaps
13908 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13909 decalsystem->freedecal++;
13910 if (decalsystem->freedecal == numdecals)
13912 decal[decalsystem->freedecal] = decal[--numdecals];
13915 decalsystem->numdecals = numdecals;
13917 if (numdecals <= 0)
13919 // if there are no decals left, reset decalsystem
13920 R_DecalSystem_Reset(decalsystem);
13924 extern skinframe_t *decalskinframe;
13925 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13928 decalsystem_t *decalsystem = &ent->decalsystem;
13937 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13940 numdecals = decalsystem->numdecals;
13944 if (r_showsurfaces.integer)
13947 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13949 R_DecalSystem_Reset(decalsystem);
13953 // if the model is static it doesn't matter what value we give for
13954 // wantnormals and wanttangents, so this logic uses only rules applicable
13955 // to a model, knowing that they are meaningless otherwise
13956 if (ent == r_refdef.scene.worldentity)
13957 RSurf_ActiveWorldEntity();
13959 RSurf_ActiveModelEntity(ent, false, false, false);
13961 decalsystem->lastupdatetime = cl.time;
13962 decal = decalsystem->decals;
13964 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13966 // update vertex positions for animated models
13967 v3f = decalsystem->vertex3f;
13968 c4f = decalsystem->color4f;
13969 t2f = decalsystem->texcoord2f;
13970 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13972 if (!decal->color4ub[0][3])
13975 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13978 // update color values for fading decals
13979 if (decal->lived >= cl_decals_time.value)
13981 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13982 alpha *= (1.0f/255.0f);
13985 alpha = 1.0f/255.0f;
13987 c4f[ 0] = decal->color4ub[0][0] * alpha;
13988 c4f[ 1] = decal->color4ub[0][1] * alpha;
13989 c4f[ 2] = decal->color4ub[0][2] * alpha;
13991 c4f[ 4] = decal->color4ub[1][0] * alpha;
13992 c4f[ 5] = decal->color4ub[1][1] * alpha;
13993 c4f[ 6] = decal->color4ub[1][2] * alpha;
13995 c4f[ 8] = decal->color4ub[2][0] * alpha;
13996 c4f[ 9] = decal->color4ub[2][1] * alpha;
13997 c4f[10] = decal->color4ub[2][2] * alpha;
14000 t2f[0] = decal->texcoord2f[0][0];
14001 t2f[1] = decal->texcoord2f[0][1];
14002 t2f[2] = decal->texcoord2f[1][0];
14003 t2f[3] = decal->texcoord2f[1][1];
14004 t2f[4] = decal->texcoord2f[2][0];
14005 t2f[5] = decal->texcoord2f[2][1];
14007 // update vertex positions for animated models
14008 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
14010 e = rsurface.modelelement3i + 3*decal->triangleindex;
14011 VectorCopy(rsurface.modelvertexposition[e[0]].vertex3f, v3f);
14012 VectorCopy(rsurface.modelvertexposition[e[1]].vertex3f, v3f + 3);
14013 VectorCopy(rsurface.modelvertexposition[e[2]].vertex3f, v3f + 6);
14017 VectorCopy(decal->vertex3f[0], v3f);
14018 VectorCopy(decal->vertex3f[1], v3f + 3);
14019 VectorCopy(decal->vertex3f[2], v3f + 6);
14022 if (r_refdef.fogenabled)
14024 alpha = RSurf_FogVertex(v3f);
14025 VectorScale(c4f, alpha, c4f);
14026 alpha = RSurf_FogVertex(v3f + 3);
14027 VectorScale(c4f + 4, alpha, c4f + 4);
14028 alpha = RSurf_FogVertex(v3f + 6);
14029 VectorScale(c4f + 8, alpha, c4f + 8);
14040 r_refdef.stats.drawndecals += numtris;
14042 // now render the decals all at once
14043 // (this assumes they all use one particle font texture!)
14044 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);
14045 R_Mesh_ResetTextureState();
14046 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
14047 GL_DepthMask(false);
14048 GL_DepthRange(0, 1);
14049 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
14050 GL_DepthTest(true);
14051 GL_CullFace(GL_NONE);
14052 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
14053 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
14054 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
14058 static void R_DrawModelDecals(void)
14062 // fade faster when there are too many decals
14063 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14064 for (i = 0;i < r_refdef.scene.numentities;i++)
14065 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14067 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
14068 for (i = 0;i < r_refdef.scene.numentities;i++)
14069 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14070 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
14072 R_DecalSystem_ApplySplatEntitiesQueue();
14074 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14075 for (i = 0;i < r_refdef.scene.numentities;i++)
14076 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14078 r_refdef.stats.totaldecals += numdecals;
14080 if (r_showsurfaces.integer)
14083 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
14085 for (i = 0;i < r_refdef.scene.numentities;i++)
14087 if (!r_refdef.viewcache.entityvisible[i])
14089 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14090 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
14094 extern cvar_t mod_collision_bih;
14095 void R_DrawDebugModel(void)
14097 entity_render_t *ent = rsurface.entity;
14098 int i, j, k, l, flagsmask;
14099 const msurface_t *surface;
14100 dp_model_t *model = ent->model;
14103 switch(vid.renderpath)
14105 case RENDERPATH_GL11:
14106 case RENDERPATH_GL13:
14107 case RENDERPATH_GL20:
14108 case RENDERPATH_CGGL:
14110 case RENDERPATH_D3D9:
14111 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14113 case RENDERPATH_D3D10:
14114 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14116 case RENDERPATH_D3D11:
14117 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14121 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
14123 R_Mesh_ResetTextureState();
14124 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
14125 GL_DepthRange(0, 1);
14126 GL_DepthTest(!r_showdisabledepthtest.integer);
14127 GL_DepthMask(false);
14128 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14130 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
14134 qboolean cullbox = ent == r_refdef.scene.worldentity;
14135 const q3mbrush_t *brush;
14136 const bih_t *bih = &model->collision_bih;
14137 const bih_leaf_t *bihleaf;
14138 float vertex3f[3][3];
14139 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
14141 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
14143 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
14145 switch (bihleaf->type)
14148 brush = model->brush.data_brushes + bihleaf->itemindex;
14149 if (brush->colbrushf && brush->colbrushf->numtriangles)
14151 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);
14152 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
14153 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
14156 case BIH_COLLISIONTRIANGLE:
14157 triangleindex = bihleaf->itemindex;
14158 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
14159 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
14160 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
14161 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);
14162 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14163 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14165 case BIH_RENDERTRIANGLE:
14166 triangleindex = bihleaf->itemindex;
14167 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
14168 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
14169 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
14170 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);
14171 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14172 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14178 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
14180 if (r_showtris.integer || r_shownormals.integer)
14182 if (r_showdisabledepthtest.integer)
14184 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14185 GL_DepthMask(false);
14189 GL_BlendFunc(GL_ONE, GL_ZERO);
14190 GL_DepthMask(true);
14192 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
14194 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
14196 rsurface.texture = R_GetCurrentTexture(surface->texture);
14197 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
14199 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
14200 if (r_showtris.value > 0)
14202 if (!rsurface.texture->currentlayers->depthmask)
14203 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
14204 else if (ent == r_refdef.scene.worldentity)
14205 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
14207 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
14208 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
14209 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
14211 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
14214 if (r_shownormals.value < 0)
14216 qglBegin(GL_LINES);
14217 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14219 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14220 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14221 qglVertex3f(v[0], v[1], v[2]);
14222 VectorMA(v, -r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14223 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14224 qglVertex3f(v[0], v[1], v[2]);
14229 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
14231 qglBegin(GL_LINES);
14232 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14234 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14235 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14236 qglVertex3f(v[0], v[1], v[2]);
14237 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14238 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14239 qglVertex3f(v[0], v[1], v[2]);
14243 qglBegin(GL_LINES);
14244 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14246 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14247 GL_Color(0, r_refdef.view.colorscale, 0, 1);
14248 qglVertex3f(v[0], v[1], v[2]);
14249 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
14250 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14251 qglVertex3f(v[0], v[1], v[2]);
14255 qglBegin(GL_LINES);
14256 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14258 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14259 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14260 qglVertex3f(v[0], v[1], v[2]);
14261 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14262 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14263 qglVertex3f(v[0], v[1], v[2]);
14270 rsurface.texture = NULL;
14274 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
14275 int r_maxsurfacelist = 0;
14276 const msurface_t **r_surfacelist = NULL;
14277 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14279 int i, j, endj, flagsmask;
14280 dp_model_t *model = r_refdef.scene.worldmodel;
14281 msurface_t *surfaces;
14282 unsigned char *update;
14283 int numsurfacelist = 0;
14287 if (r_maxsurfacelist < model->num_surfaces)
14289 r_maxsurfacelist = model->num_surfaces;
14291 Mem_Free((msurface_t**)r_surfacelist);
14292 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14295 RSurf_ActiveWorldEntity();
14297 surfaces = model->data_surfaces;
14298 update = model->brushq1.lightmapupdateflags;
14300 // update light styles on this submodel
14301 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14303 model_brush_lightstyleinfo_t *style;
14304 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14306 if (style->value != r_refdef.scene.lightstylevalue[style->style])
14308 int *list = style->surfacelist;
14309 style->value = r_refdef.scene.lightstylevalue[style->style];
14310 for (j = 0;j < style->numsurfaces;j++)
14311 update[list[j]] = true;
14316 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14320 R_DrawDebugModel();
14321 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14325 rsurface.lightmaptexture = NULL;
14326 rsurface.deluxemaptexture = NULL;
14327 rsurface.uselightmaptexture = false;
14328 rsurface.texture = NULL;
14329 rsurface.rtlight = NULL;
14330 numsurfacelist = 0;
14331 // add visible surfaces to draw list
14332 for (i = 0;i < model->nummodelsurfaces;i++)
14334 j = model->sortedmodelsurfaces[i];
14335 if (r_refdef.viewcache.world_surfacevisible[j])
14336 r_surfacelist[numsurfacelist++] = surfaces + j;
14338 // update lightmaps if needed
14339 if (model->brushq1.firstrender)
14341 model->brushq1.firstrender = false;
14342 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14344 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14348 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14349 if (r_refdef.viewcache.world_surfacevisible[j])
14351 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14353 // don't do anything if there were no surfaces
14354 if (!numsurfacelist)
14356 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14359 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14360 GL_AlphaTest(false);
14362 // add to stats if desired
14363 if (r_speeds.integer && !skysurfaces && !depthonly)
14365 r_refdef.stats.world_surfaces += numsurfacelist;
14366 for (j = 0;j < numsurfacelist;j++)
14367 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
14370 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14373 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14375 int i, j, endj, flagsmask;
14376 dp_model_t *model = ent->model;
14377 msurface_t *surfaces;
14378 unsigned char *update;
14379 int numsurfacelist = 0;
14383 if (r_maxsurfacelist < model->num_surfaces)
14385 r_maxsurfacelist = model->num_surfaces;
14387 Mem_Free((msurface_t **)r_surfacelist);
14388 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14391 // if the model is static it doesn't matter what value we give for
14392 // wantnormals and wanttangents, so this logic uses only rules applicable
14393 // to a model, knowing that they are meaningless otherwise
14394 if (ent == r_refdef.scene.worldentity)
14395 RSurf_ActiveWorldEntity();
14396 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14397 RSurf_ActiveModelEntity(ent, false, false, false);
14399 RSurf_ActiveModelEntity(ent, true, true, true);
14400 else if (depthonly)
14402 switch (vid.renderpath)
14404 case RENDERPATH_GL20:
14405 case RENDERPATH_CGGL:
14406 case RENDERPATH_D3D9:
14407 case RENDERPATH_D3D10:
14408 case RENDERPATH_D3D11:
14409 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14411 case RENDERPATH_GL13:
14412 case RENDERPATH_GL11:
14413 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14419 switch (vid.renderpath)
14421 case RENDERPATH_GL20:
14422 case RENDERPATH_CGGL:
14423 case RENDERPATH_D3D9:
14424 case RENDERPATH_D3D10:
14425 case RENDERPATH_D3D11:
14426 RSurf_ActiveModelEntity(ent, true, true, false);
14428 case RENDERPATH_GL13:
14429 case RENDERPATH_GL11:
14430 RSurf_ActiveModelEntity(ent, true, false, false);
14435 surfaces = model->data_surfaces;
14436 update = model->brushq1.lightmapupdateflags;
14438 // update light styles
14439 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14441 model_brush_lightstyleinfo_t *style;
14442 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14444 if (style->value != r_refdef.scene.lightstylevalue[style->style])
14446 int *list = style->surfacelist;
14447 style->value = r_refdef.scene.lightstylevalue[style->style];
14448 for (j = 0;j < style->numsurfaces;j++)
14449 update[list[j]] = true;
14454 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14458 R_DrawDebugModel();
14459 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14463 rsurface.lightmaptexture = NULL;
14464 rsurface.deluxemaptexture = NULL;
14465 rsurface.uselightmaptexture = false;
14466 rsurface.texture = NULL;
14467 rsurface.rtlight = NULL;
14468 numsurfacelist = 0;
14469 // add visible surfaces to draw list
14470 for (i = 0;i < model->nummodelsurfaces;i++)
14471 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14472 // don't do anything if there were no surfaces
14473 if (!numsurfacelist)
14475 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14478 // update lightmaps if needed
14482 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14487 R_BuildLightMap(ent, surfaces + j);
14492 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14494 R_BuildLightMap(ent, surfaces + j);
14495 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14496 GL_AlphaTest(false);
14498 // add to stats if desired
14499 if (r_speeds.integer && !skysurfaces && !depthonly)
14501 r_refdef.stats.entities_surfaces += numsurfacelist;
14502 for (j = 0;j < numsurfacelist;j++)
14503 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14506 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14509 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14511 static texture_t texture;
14512 static msurface_t surface;
14513 const msurface_t *surfacelist = &surface;
14515 // fake enough texture and surface state to render this geometry
14517 texture.update_lastrenderframe = -1; // regenerate this texture
14518 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14519 texture.currentskinframe = skinframe;
14520 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14521 texture.offsetmapping = OFFSETMAPPING_OFF;
14522 texture.offsetscale = 1;
14523 texture.specularscalemod = 1;
14524 texture.specularpowermod = 1;
14526 surface.texture = &texture;
14527 surface.num_triangles = numtriangles;
14528 surface.num_firsttriangle = firsttriangle;
14529 surface.num_vertices = numvertices;
14530 surface.num_firstvertex = firstvertex;
14533 rsurface.texture = R_GetCurrentTexture(surface.texture);
14534 rsurface.lightmaptexture = NULL;
14535 rsurface.deluxemaptexture = NULL;
14536 rsurface.uselightmaptexture = false;
14537 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14540 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)
14542 static msurface_t surface;
14543 const msurface_t *surfacelist = &surface;
14545 // fake enough texture and surface state to render this geometry
14546 surface.texture = texture;
14547 surface.num_triangles = numtriangles;
14548 surface.num_firsttriangle = firsttriangle;
14549 surface.num_vertices = numvertices;
14550 surface.num_firstvertex = firstvertex;
14553 rsurface.texture = R_GetCurrentTexture(surface.texture);
14554 rsurface.lightmaptexture = NULL;
14555 rsurface.deluxemaptexture = NULL;
14556 rsurface.uselightmaptexture = false;
14557 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);