2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
30 #include "dpsoftrast.h"
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
68 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
74 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
75 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
81 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
82 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
83 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
84 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
85 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
86 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
87 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
88 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
89 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
90 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
91 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
92 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
93 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
94 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
95 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
97 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
98 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
99 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
101 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
102 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
103 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
104 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
105 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
106 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
107 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
108 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
109 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
110 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
111 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
112 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
113 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
114 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
115 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
117 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
118 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
119 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
121 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
122 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
123 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
124 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
125 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
126 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
127 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
128 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
130 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
131 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
133 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
134 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
137 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
139 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
140 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
141 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
143 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
144 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
145 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
146 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
147 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
148 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
149 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
150 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
151 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
152 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
153 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
154 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
155 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
157 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
158 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
159 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
160 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
161 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
162 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
164 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
165 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
166 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
167 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
169 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
170 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
171 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
172 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
173 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
174 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
175 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
177 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
178 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
179 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
180 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
182 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
184 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
186 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
188 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
189 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
190 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
191 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
192 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
193 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
194 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "15", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
195 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
196 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
198 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
199 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
201 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
203 extern cvar_t v_glslgamma;
205 extern qboolean v_flipped_state;
207 static struct r_bloomstate_s
212 int bloomwidth, bloomheight;
214 int screentexturewidth, screentextureheight;
215 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
217 int bloomtexturewidth, bloomtextureheight;
218 rtexture_t *texture_bloom;
220 // arrays for rendering the screen passes
221 float screentexcoord2f[8];
222 float bloomtexcoord2f[8];
223 float offsettexcoord2f[8];
225 r_viewport_t viewport;
229 r_waterstate_t r_waterstate;
231 /// shadow volume bsp struct with automatically growing nodes buffer
234 rtexture_t *r_texture_blanknormalmap;
235 rtexture_t *r_texture_white;
236 rtexture_t *r_texture_grey128;
237 rtexture_t *r_texture_black;
238 rtexture_t *r_texture_notexture;
239 rtexture_t *r_texture_whitecube;
240 rtexture_t *r_texture_normalizationcube;
241 rtexture_t *r_texture_fogattenuation;
242 rtexture_t *r_texture_fogheighttexture;
243 rtexture_t *r_texture_gammaramps;
244 unsigned int r_texture_gammaramps_serial;
245 //rtexture_t *r_texture_fogintensity;
246 rtexture_t *r_texture_reflectcube;
248 // TODO: hash lookups?
249 typedef struct cubemapinfo_s
256 int r_texture_numcubemaps;
257 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
259 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
260 unsigned int r_numqueries;
261 unsigned int r_maxqueries;
263 typedef struct r_qwskincache_s
265 char name[MAX_QPATH];
266 skinframe_t *skinframe;
270 static r_qwskincache_t *r_qwskincache;
271 static int r_qwskincache_size;
273 /// vertex coordinates for a quad that covers the screen exactly
274 extern const float r_screenvertex3f[12];
275 extern const float r_d3dscreenvertex3f[12];
276 const float r_screenvertex3f[12] =
283 const float r_d3dscreenvertex3f[12] =
291 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
294 for (i = 0;i < verts;i++)
305 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
308 for (i = 0;i < verts;i++)
318 // FIXME: move this to client?
321 if (gamemode == GAME_NEHAHRA)
323 Cvar_Set("gl_fogenable", "0");
324 Cvar_Set("gl_fogdensity", "0.2");
325 Cvar_Set("gl_fogred", "0.3");
326 Cvar_Set("gl_foggreen", "0.3");
327 Cvar_Set("gl_fogblue", "0.3");
329 r_refdef.fog_density = 0;
330 r_refdef.fog_red = 0;
331 r_refdef.fog_green = 0;
332 r_refdef.fog_blue = 0;
333 r_refdef.fog_alpha = 1;
334 r_refdef.fog_start = 0;
335 r_refdef.fog_end = 16384;
336 r_refdef.fog_height = 1<<30;
337 r_refdef.fog_fadedepth = 128;
338 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
341 static void R_BuildBlankTextures(void)
343 unsigned char data[4];
344 data[2] = 128; // normal X
345 data[1] = 128; // normal Y
346 data[0] = 255; // normal Z
347 data[3] = 128; // height
348 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
353 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
358 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
363 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
366 static void R_BuildNoTexture(void)
369 unsigned char pix[16][16][4];
370 // this makes a light grey/dark grey checkerboard texture
371 for (y = 0;y < 16;y++)
373 for (x = 0;x < 16;x++)
375 if ((y < 8) ^ (x < 8))
391 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
394 static void R_BuildWhiteCube(void)
396 unsigned char data[6*1*1*4];
397 memset(data, 255, sizeof(data));
398 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
401 static void R_BuildNormalizationCube(void)
405 vec_t s, t, intensity;
408 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
409 for (side = 0;side < 6;side++)
411 for (y = 0;y < NORMSIZE;y++)
413 for (x = 0;x < NORMSIZE;x++)
415 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
416 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
451 intensity = 127.0f / sqrt(DotProduct(v, v));
452 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
453 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
454 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
455 data[((side*64+y)*64+x)*4+3] = 255;
459 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
463 static void R_BuildFogTexture(void)
467 unsigned char data1[FOGWIDTH][4];
468 //unsigned char data2[FOGWIDTH][4];
471 r_refdef.fogmasktable_start = r_refdef.fog_start;
472 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
473 r_refdef.fogmasktable_range = r_refdef.fogrange;
474 r_refdef.fogmasktable_density = r_refdef.fog_density;
476 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
477 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
479 d = (x * r - r_refdef.fogmasktable_start);
480 if(developer_extra.integer)
481 Con_DPrintf("%f ", d);
483 if (r_fog_exp2.integer)
484 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
486 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
487 if(developer_extra.integer)
488 Con_DPrintf(" : %f ", alpha);
489 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
490 if(developer_extra.integer)
491 Con_DPrintf(" = %f\n", alpha);
492 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
495 for (x = 0;x < FOGWIDTH;x++)
497 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
502 //data2[x][0] = 255 - b;
503 //data2[x][1] = 255 - b;
504 //data2[x][2] = 255 - b;
507 if (r_texture_fogattenuation)
509 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
510 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
514 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
515 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
519 static void R_BuildFogHeightTexture(void)
521 unsigned char *inpixels;
529 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
530 if (r_refdef.fogheighttexturename[0])
531 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
534 r_refdef.fog_height_tablesize = 0;
535 if (r_texture_fogheighttexture)
536 R_FreeTexture(r_texture_fogheighttexture);
537 r_texture_fogheighttexture = NULL;
538 if (r_refdef.fog_height_table2d)
539 Mem_Free(r_refdef.fog_height_table2d);
540 r_refdef.fog_height_table2d = NULL;
541 if (r_refdef.fog_height_table1d)
542 Mem_Free(r_refdef.fog_height_table1d);
543 r_refdef.fog_height_table1d = NULL;
547 r_refdef.fog_height_tablesize = size;
548 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
549 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
550 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
552 // LordHavoc: now the magic - what is that table2d for? it is a cooked
553 // average fog color table accounting for every fog layer between a point
554 // and the camera. (Note: attenuation is handled separately!)
555 for (y = 0;y < size;y++)
557 for (x = 0;x < size;x++)
563 for (j = x;j <= y;j++)
565 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
571 for (j = x;j >= y;j--)
573 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
578 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
579 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
580 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
581 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
584 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
587 //=======================================================================================================================================================
589 static const char *builtinshaderstring =
590 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
591 "// written by Forest 'LordHavoc' Hale\n"
592 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
594 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
597 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
598 "#define USELIGHTMAP\n"
600 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
601 "#define USEEYEVECTOR\n"
604 "#ifdef USESHADOWMAP2D\n"
605 "# ifdef GL_EXT_gpu_shader4\n"
606 "# extension GL_EXT_gpu_shader4 : enable\n"
608 "# ifdef GL_ARB_texture_gather\n"
609 "# extension GL_ARB_texture_gather : enable\n"
611 "# ifdef GL_AMD_texture_texture4\n"
612 "# extension GL_AMD_texture_texture4 : enable\n"
617 "//#ifdef USESHADOWSAMPLER\n"
618 "//# extension GL_ARB_shadow : enable\n"
621 "//#ifdef __GLSL_CG_DATA_TYPES\n"
622 "//# define myhalf half\n"
623 "//# define myhalf2 half2\n"
624 "//# define myhalf3 half3\n"
625 "//# define myhalf4 half4\n"
627 "# define myhalf float\n"
628 "# define myhalf2 vec2\n"
629 "# define myhalf3 vec3\n"
630 "# define myhalf4 vec4\n"
633 "#ifdef VERTEX_SHADER\n"
634 "uniform mat4 ModelViewProjectionMatrix;\n"
637 "#ifdef MODE_DEPTH_OR_SHADOW\n"
638 "#ifdef VERTEX_SHADER\n"
641 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
644 "#else // !MODE_DEPTH_ORSHADOW\n"
649 "#ifdef MODE_SHOWDEPTH\n"
650 "#ifdef VERTEX_SHADER\n"
653 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
654 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
658 "#ifdef FRAGMENT_SHADER\n"
661 " gl_FragColor = gl_Color;\n"
664 "#else // !MODE_SHOWDEPTH\n"
669 "#ifdef MODE_POSTPROCESS\n"
670 "varying vec2 TexCoord1;\n"
671 "varying vec2 TexCoord2;\n"
673 "#ifdef VERTEX_SHADER\n"
676 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
677 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
679 " TexCoord2 = gl_MultiTexCoord4.xy;\n"
684 "#ifdef FRAGMENT_SHADER\n"
685 "uniform sampler2D Texture_First;\n"
687 "uniform sampler2D Texture_Second;\n"
688 "uniform vec4 BloomColorSubtract;\n"
690 "#ifdef USEGAMMARAMPS\n"
691 "uniform sampler2D Texture_GammaRamps;\n"
693 "#ifdef USESATURATION\n"
694 "uniform float Saturation;\n"
696 "#ifdef USEVIEWTINT\n"
697 "uniform vec4 ViewTintColor;\n"
699 "//uncomment these if you want to use them:\n"
700 "uniform vec4 UserVec1;\n"
701 "uniform vec4 UserVec2;\n"
702 "// uniform vec4 UserVec3;\n"
703 "// uniform vec4 UserVec4;\n"
704 "// uniform float ClientTime;\n"
705 "uniform vec2 PixelSize;\n"
708 " gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
710 " gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
712 "#ifdef USEVIEWTINT\n"
713 " gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
716 "#ifdef USEPOSTPROCESSING\n"
717 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
718 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
719 " float sobel = 1.0;\n"
720 " // vec2 ts = textureSize(Texture_First, 0);\n"
721 " // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
722 " vec2 px = PixelSize;\n"
723 " vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
724 " vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, 0.0)).rgb;\n"
725 " vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
726 " vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
727 " vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x, 0.0)).rgb;\n"
728 " vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
729 " vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
730 " vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2( 0.0,-px.y)).rgb;\n"
731 " vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
732 " vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
733 " vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2( 0.0, px.y)).rgb;\n"
734 " vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
735 " float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
736 " float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
737 " float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
738 " float px4 = 1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
739 " float px5 = 2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
740 " float px6 = 1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
741 " float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
742 " float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
743 " float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
744 " float py4 = 1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
745 " float py5 = 2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
746 " float py6 = 1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
747 " sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
748 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
749 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
750 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
751 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
752 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
753 " gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
754 " gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
757 "#ifdef USESATURATION\n"
758 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
759 " float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
760 " // 'vampire sight' effect, wheres red is compensated\n"
761 " #ifdef SATURATION_REDCOMPENSATE\n"
762 " float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
763 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
764 " gl_FragColor.r += rboost;\n"
766 " // normal desaturation\n"
767 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
768 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
772 "#ifdef USEGAMMARAMPS\n"
773 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
774 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
775 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
779 "#else // !MODE_POSTPROCESS\n"
784 "#ifdef MODE_GENERIC\n"
785 "#ifdef USEDIFFUSE\n"
786 "varying vec2 TexCoord1;\n"
788 "#ifdef USESPECULAR\n"
789 "varying vec2 TexCoord2;\n"
791 "#ifdef VERTEX_SHADER\n"
794 " gl_FrontColor = gl_Color;\n"
795 "#ifdef USEDIFFUSE\n"
796 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
798 "#ifdef USESPECULAR\n"
799 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
801 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
805 "#ifdef FRAGMENT_SHADER\n"
806 "#ifdef USEDIFFUSE\n"
807 "uniform sampler2D Texture_First;\n"
809 "#ifdef USESPECULAR\n"
810 "uniform sampler2D Texture_Second;\n"
815 "#ifdef USEVIEWTINT\n"
816 " gl_FragColor = gl_Color;\n"
818 " gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
820 "#ifdef USEDIFFUSE\n"
821 " gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
824 "#ifdef USESPECULAR\n"
825 " vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
826 "# ifdef USECOLORMAPPING\n"
827 " gl_FragColor *= tex2;\n"
830 " gl_FragColor += tex2;\n"
832 "# ifdef USEVERTEXTEXTUREBLEND\n"
833 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
838 "#else // !MODE_GENERIC\n"
843 "#ifdef MODE_BLOOMBLUR\n"
844 "varying TexCoord;\n"
845 "#ifdef VERTEX_SHADER\n"
848 " gl_FrontColor = gl_Color;\n"
849 " TexCoord = gl_MultiTexCoord0.xy;\n"
850 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
854 "#ifdef FRAGMENT_SHADER\n"
855 "uniform sampler2D Texture_First;\n"
856 "uniform vec4 BloomBlur_Parameters;\n"
861 " vec2 tc = TexCoord;\n"
862 " vec3 color = texture2D(Texture_First, tc).rgb;\n"
863 " tc += BloomBlur_Parameters.xy;\n"
864 " for (i = 1;i < SAMPLES;i++)\n"
866 " color += texture2D(Texture_First, tc).rgb;\n"
867 " tc += BloomBlur_Parameters.xy;\n"
869 " gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
872 "#else // !MODE_BLOOMBLUR\n"
873 "#ifdef MODE_REFRACTION\n"
874 "varying vec2 TexCoord;\n"
875 "varying vec4 ModelViewProjectionPosition;\n"
876 "uniform mat4 TexMatrix;\n"
877 "#ifdef VERTEX_SHADER\n"
881 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
882 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
883 " ModelViewProjectionPosition = gl_Position;\n"
887 "#ifdef FRAGMENT_SHADER\n"
888 "uniform sampler2D Texture_Normal;\n"
889 "uniform sampler2D Texture_Refraction;\n"
890 "uniform sampler2D Texture_Reflection;\n"
892 "uniform vec4 DistortScaleRefractReflect;\n"
893 "uniform vec4 ScreenScaleRefractReflect;\n"
894 "uniform vec4 ScreenCenterRefractReflect;\n"
895 "uniform vec4 RefractColor;\n"
896 "uniform vec4 ReflectColor;\n"
897 "uniform float ReflectFactor;\n"
898 "uniform float ReflectOffset;\n"
902 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
903 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
904 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
905 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
906 " // FIXME temporary hack to detect the case that the reflection\n"
907 " // gets blackened at edges due to leaving the area that contains actual\n"
909 " // Remove this 'ack once we have a better way to stop this thing from\n"
911 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
912 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
913 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
914 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
915 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
916 " gl_FragColor = vec4(texture2D(Texture_Refraction, ScreenTexCoord).rgb, 1.0) * RefractColor;\n"
919 "#else // !MODE_REFRACTION\n"
924 "#ifdef MODE_WATER\n"
925 "varying vec2 TexCoord;\n"
926 "varying vec3 EyeVector;\n"
927 "varying vec4 ModelViewProjectionPosition;\n"
928 "#ifdef VERTEX_SHADER\n"
929 "uniform vec3 EyePosition;\n"
930 "uniform mat4 TexMatrix;\n"
934 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
935 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
936 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
937 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
938 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
939 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
940 " ModelViewProjectionPosition = gl_Position;\n"
944 "#ifdef FRAGMENT_SHADER\n"
945 "uniform sampler2D Texture_Normal;\n"
946 "uniform sampler2D Texture_Refraction;\n"
947 "uniform sampler2D Texture_Reflection;\n"
949 "uniform vec4 DistortScaleRefractReflect;\n"
950 "uniform vec4 ScreenScaleRefractReflect;\n"
951 "uniform vec4 ScreenCenterRefractReflect;\n"
952 "uniform vec4 RefractColor;\n"
953 "uniform vec4 ReflectColor;\n"
954 "uniform float ReflectFactor;\n"
955 "uniform float ReflectOffset;\n"
956 "uniform float ClientTime;\n"
957 "#ifdef USENORMALMAPSCROLLBLEND\n"
958 "uniform vec2 NormalmapScrollBlend;\n"
963 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
964 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
965 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
966 " //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
967 " // slight water animation via 2 layer scrolling (todo: tweak)\n"
968 " #ifdef USENORMALMAPSCROLLBLEND\n"
969 " vec3 normal = texture2D(Texture_Normal, (TexCoord + vec2(0.08, 0.08)*ClientTime*NormalmapScrollBlend.x*0.5)*NormalmapScrollBlend.y).rgb - vec3(1.0);\n"
970 " normal += texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime*NormalmapScrollBlend.x)*NormalmapScrollBlend.y*0.75).rgb;\n"
971 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(normal) + vec3(0.15)).xyxy * DistortScaleRefractReflect;\n"
973 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
975 " // FIXME temporary hack to detect the case that the reflection\n"
976 " // gets blackened at edges due to leaving the area that contains actual\n"
978 " // Remove this 'ack once we have a better way to stop this thing from\n"
980 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, 0.01)).rgb) / 0.002);\n"
981 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, -0.01)).rgb) / 0.002);\n"
982 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, 0.01)).rgb) / 0.002);\n"
983 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, -0.01)).rgb) / 0.002);\n"
984 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
985 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, 0.005)).rgb) / 0.002);\n"
986 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, -0.005)).rgb) / 0.002);\n"
987 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, 0.005)).rgb) / 0.002);\n"
988 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, -0.005)).rgb) / 0.002);\n"
989 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
990 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
991 " gl_FragColor = mix(vec4(texture2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, vec4(texture2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
994 "#else // !MODE_WATER\n"
999 "// common definitions between vertex shader and fragment shader:\n"
1001 "varying vec2 TexCoord;\n"
1002 "#ifdef USEVERTEXTEXTUREBLEND\n"
1003 "varying vec2 TexCoord2;\n"
1005 "#ifdef USELIGHTMAP\n"
1006 "varying vec2 TexCoordLightmap;\n"
1009 "#ifdef MODE_LIGHTSOURCE\n"
1010 "varying vec3 CubeVector;\n"
1013 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
1014 "varying vec3 LightVector;\n"
1017 "#ifdef USEEYEVECTOR\n"
1018 "varying vec3 EyeVector;\n"
1021 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
1024 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
1025 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
1026 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
1027 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
1030 "#ifdef USEREFLECTION\n"
1031 "varying vec4 ModelViewProjectionPosition;\n"
1033 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1034 "uniform vec3 LightPosition;\n"
1035 "varying vec4 ModelViewPosition;\n"
1038 "#ifdef MODE_LIGHTSOURCE\n"
1039 "uniform vec3 LightPosition;\n"
1041 "uniform vec3 EyePosition;\n"
1042 "#ifdef MODE_LIGHTDIRECTION\n"
1043 "uniform vec3 LightDir;\n"
1045 "uniform vec4 FogPlane;\n"
1047 "#ifdef USESHADOWMAPORTHO\n"
1048 "varying vec3 ShadowMapTC;\n"
1055 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
1057 "// fragment shader specific:\n"
1058 "#ifdef FRAGMENT_SHADER\n"
1060 "uniform sampler2D Texture_Normal;\n"
1061 "uniform sampler2D Texture_Color;\n"
1062 "uniform sampler2D Texture_Gloss;\n"
1064 "uniform sampler2D Texture_Glow;\n"
1066 "#ifdef USEVERTEXTEXTUREBLEND\n"
1067 "uniform sampler2D Texture_SecondaryNormal;\n"
1068 "uniform sampler2D Texture_SecondaryColor;\n"
1069 "uniform sampler2D Texture_SecondaryGloss;\n"
1071 "uniform sampler2D Texture_SecondaryGlow;\n"
1074 "#ifdef USECOLORMAPPING\n"
1075 "uniform sampler2D Texture_Pants;\n"
1076 "uniform sampler2D Texture_Shirt;\n"
1079 "#ifdef USEFOGHEIGHTTEXTURE\n"
1080 "uniform sampler2D Texture_FogHeightTexture;\n"
1082 "uniform sampler2D Texture_FogMask;\n"
1084 "#ifdef USELIGHTMAP\n"
1085 "uniform sampler2D Texture_Lightmap;\n"
1087 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1088 "uniform sampler2D Texture_Deluxemap;\n"
1090 "#ifdef USEREFLECTION\n"
1091 "uniform sampler2D Texture_Reflection;\n"
1094 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1095 "uniform sampler2D Texture_ScreenDepth;\n"
1096 "uniform sampler2D Texture_ScreenNormalMap;\n"
1098 "#ifdef USEDEFERREDLIGHTMAP\n"
1099 "uniform sampler2D Texture_ScreenDiffuse;\n"
1100 "uniform sampler2D Texture_ScreenSpecular;\n"
1103 "uniform myhalf3 Color_Pants;\n"
1104 "uniform myhalf3 Color_Shirt;\n"
1105 "uniform myhalf3 FogColor;\n"
1108 "uniform float FogRangeRecip;\n"
1109 "uniform float FogPlaneViewDist;\n"
1110 "uniform float FogHeightFade;\n"
1111 "vec3 FogVertex(vec3 surfacecolor)\n"
1113 " vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1114 " float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1116 "#ifdef USEFOGHEIGHTTEXTURE\n"
1117 " vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1118 " fogfrac = fogheightpixel.a;\n"
1119 " return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1121 "# ifdef USEFOGOUTSIDE\n"
1122 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1124 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1126 " return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1131 "#ifdef USEOFFSETMAPPING\n"
1132 "uniform float OffsetMapping_Scale;\n"
1133 "vec2 OffsetMapping(vec2 TexCoord)\n"
1135 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1136 " // 14 sample relief mapping: linear search and then binary search\n"
1137 " // this basically steps forward a small amount repeatedly until it finds\n"
1138 " // itself inside solid, then jitters forward and back using decreasing\n"
1139 " // amounts to find the impact\n"
1140 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1141 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1142 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1143 " vec3 RT = vec3(TexCoord, 1);\n"
1144 " OffsetVector *= 0.1;\n"
1145 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1146 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1147 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1148 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1149 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1150 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1151 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1152 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1153 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1154 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
1155 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
1156 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
1157 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
1158 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1161 " // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1162 " // this basically moves forward the full distance, and then backs up based\n"
1163 " // on height of samples\n"
1164 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1165 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1166 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1167 " TexCoord += OffsetVector;\n"
1168 " OffsetVector *= 0.5;\n"
1169 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1170 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1171 " return TexCoord;\n"
1174 "#endif // USEOFFSETMAPPING\n"
1176 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1177 "uniform sampler2D Texture_Attenuation;\n"
1178 "uniform samplerCube Texture_Cube;\n"
1181 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1183 "#ifdef USESHADOWMAP2D\n"
1184 "# ifdef USESHADOWSAMPLER\n"
1185 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1187 "uniform sampler2D Texture_ShadowMap2D;\n"
1191 "#ifdef USESHADOWMAPVSDCT\n"
1192 "uniform samplerCube Texture_CubeProjection;\n"
1195 "#if defined(USESHADOWMAP2D)\n"
1196 "uniform vec2 ShadowMap_TextureScale;\n"
1197 "uniform vec4 ShadowMap_Parameters;\n"
1200 "#if defined(USESHADOWMAP2D)\n"
1201 "# ifdef USESHADOWMAPORTHO\n"
1202 "# define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1204 "# ifdef USESHADOWMAPVSDCT\n"
1205 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1207 " vec3 adir = abs(dir);\n"
1208 " vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1209 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1210 " return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1213 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1215 " vec3 adir = abs(dir);\n"
1216 " float ma = adir.z;\n"
1217 " vec4 proj = vec4(dir, 2.5);\n"
1218 " if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1219 " if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1220 " vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1221 " return vec3(proj.xy * aparams.x + vec2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1225 "#endif // defined(USESHADOWMAP2D)\n"
1227 "# ifdef USESHADOWMAP2D\n"
1228 "float ShadowMapCompare(vec3 dir)\n"
1230 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1233 "# ifdef USESHADOWSAMPLER\n"
1234 "# ifdef USESHADOWMAPPCF\n"
1235 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1236 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1237 " f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1239 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1242 "# ifdef USESHADOWMAPPCF\n"
1243 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1244 "# ifdef GL_ARB_texture_gather\n"
1245 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1247 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1249 " vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1250 "# if USESHADOWMAPPCF > 1\n"
1251 " vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1252 " vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1253 " vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1254 " vec4 group4 = step(shadowmaptc.z, texval(-2.0, 0.0));\n"
1255 " vec4 group5 = step(shadowmaptc.z, texval( 0.0, 0.0));\n"
1256 " vec4 group6 = step(shadowmaptc.z, texval( 2.0, 0.0));\n"
1257 " vec4 group7 = step(shadowmaptc.z, texval(-2.0, 2.0));\n"
1258 " vec4 group8 = step(shadowmaptc.z, texval( 0.0, 2.0));\n"
1259 " vec4 group9 = step(shadowmaptc.z, texval( 2.0, 2.0));\n"
1260 " vec4 locols = vec4(group1.ab, group3.ab);\n"
1261 " vec4 hicols = vec4(group7.rg, group9.rg);\n"
1262 " locols.yz += group2.ab;\n"
1263 " hicols.yz += group8.rg;\n"
1264 " vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1265 " vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1266 " mix(locols, hicols, offset.y);\n"
1267 " vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1268 " cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1269 " f = dot(cols, vec4(1.0/25.0));\n"
1271 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1272 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1273 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1274 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1275 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1276 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1277 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1280 "# ifdef GL_EXT_gpu_shader4\n"
1281 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1283 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1285 "# if USESHADOWMAPPCF > 1\n"
1286 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1287 " center *= ShadowMap_TextureScale;\n"
1288 " vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1289 " vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0), texval( 2.0, 0.0)));\n"
1290 " vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0), texval( 2.0, 1.0)));\n"
1291 " vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0, 2.0), texval( 0.0, 2.0), texval( 1.0, 2.0), texval( 2.0, 2.0)));\n"
1292 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1293 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1295 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1296 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1297 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1298 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1299 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1300 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1304 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1307 "# ifdef USESHADOWMAPORTHO\n"
1308 " return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1314 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1315 "#endif // FRAGMENT_SHADER\n"
1320 "#ifdef MODE_DEFERREDGEOMETRY\n"
1321 "#ifdef VERTEX_SHADER\n"
1322 "uniform mat4 TexMatrix;\n"
1323 "#ifdef USEVERTEXTEXTUREBLEND\n"
1324 "uniform mat4 BackgroundTexMatrix;\n"
1326 "uniform mat4 ModelViewMatrix;\n"
1329 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1330 "#ifdef USEVERTEXTEXTUREBLEND\n"
1331 " gl_FrontColor = gl_Color;\n"
1332 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1335 " // transform unnormalized eye direction into tangent space\n"
1336 "#ifdef USEOFFSETMAPPING\n"
1337 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1338 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1339 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1340 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1343 " VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1344 " VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1345 " VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1346 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1348 "#endif // VERTEX_SHADER\n"
1350 "#ifdef FRAGMENT_SHADER\n"
1353 "#ifdef USEOFFSETMAPPING\n"
1354 " // apply offsetmapping\n"
1355 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1356 "#define TexCoord TexCoordOffset\n"
1359 "#ifdef USEALPHAKILL\n"
1360 " if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1364 "#ifdef USEVERTEXTEXTUREBLEND\n"
1365 " float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1366 " float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1367 " //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1368 " //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1371 "#ifdef USEVERTEXTEXTUREBLEND\n"
1372 " vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1373 " float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1375 " vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1376 " float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1379 " gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1381 "#endif // FRAGMENT_SHADER\n"
1382 "#else // !MODE_DEFERREDGEOMETRY\n"
1387 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1388 "#ifdef VERTEX_SHADER\n"
1389 "uniform mat4 ModelViewMatrix;\n"
1392 " ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1393 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1395 "#endif // VERTEX_SHADER\n"
1397 "#ifdef FRAGMENT_SHADER\n"
1398 "uniform mat4 ViewToLight;\n"
1399 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1400 "uniform vec2 ScreenToDepth;\n"
1401 "uniform myhalf3 DeferredColor_Ambient;\n"
1402 "uniform myhalf3 DeferredColor_Diffuse;\n"
1403 "#ifdef USESPECULAR\n"
1404 "uniform myhalf3 DeferredColor_Specular;\n"
1405 "uniform myhalf SpecularPower;\n"
1407 "uniform myhalf2 PixelToScreenTexCoord;\n"
1410 " // calculate viewspace pixel position\n"
1411 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1413 " position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1414 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1415 " // decode viewspace pixel normal\n"
1416 " myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1417 " myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1418 " // surfacenormal = pixel normal in viewspace\n"
1419 " // LightVector = pixel to light in viewspace\n"
1420 " // CubeVector = position in lightspace\n"
1421 " // eyevector = pixel to view in viewspace\n"
1422 " vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1423 " myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1424 "#ifdef USEDIFFUSE\n"
1425 " // calculate diffuse shading\n"
1426 " myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1427 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1429 "#ifdef USESPECULAR\n"
1430 " // calculate directional shading\n"
1431 " vec3 eyevector = position * -1.0;\n"
1432 "# ifdef USEEXACTSPECULARMATH\n"
1433 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1435 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1436 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1440 "#if defined(USESHADOWMAP2D)\n"
1441 " fade *= ShadowMapCompare(CubeVector);\n"
1444 "#ifdef USEDIFFUSE\n"
1445 " gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1447 " gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1449 "#ifdef USESPECULAR\n"
1450 " gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1452 " gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1455 "# ifdef USECUBEFILTER\n"
1456 " vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1457 " gl_FragData[0].rgb *= cubecolor;\n"
1458 " gl_FragData[1].rgb *= cubecolor;\n"
1461 "#endif // FRAGMENT_SHADER\n"
1462 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1467 "#ifdef VERTEX_SHADER\n"
1468 "uniform mat4 TexMatrix;\n"
1469 "#ifdef USEVERTEXTEXTUREBLEND\n"
1470 "uniform mat4 BackgroundTexMatrix;\n"
1472 "#ifdef MODE_LIGHTSOURCE\n"
1473 "uniform mat4 ModelToLight;\n"
1475 "#ifdef USESHADOWMAPORTHO\n"
1476 "uniform mat4 ShadowMapMatrix;\n"
1480 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1481 " gl_FrontColor = gl_Color;\n"
1483 " // copy the surface texcoord\n"
1484 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1485 "#ifdef USEVERTEXTEXTUREBLEND\n"
1486 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1488 "#ifdef USELIGHTMAP\n"
1489 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1492 "#ifdef MODE_LIGHTSOURCE\n"
1493 " // transform vertex position into light attenuation/cubemap space\n"
1494 " // (-1 to +1 across the light box)\n"
1495 " CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1497 "# ifdef USEDIFFUSE\n"
1498 " // transform unnormalized light direction into tangent space\n"
1499 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
1500 " // normalize it per pixel)\n"
1501 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1502 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1503 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1504 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1508 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1509 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1510 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1511 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1514 " // transform unnormalized eye direction into tangent space\n"
1515 "#ifdef USEEYEVECTOR\n"
1516 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1517 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1518 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1519 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1523 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1524 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1527 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1528 " VectorS = gl_MultiTexCoord1.xyz;\n"
1529 " VectorT = gl_MultiTexCoord2.xyz;\n"
1530 " VectorR = gl_MultiTexCoord3.xyz;\n"
1533 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1534 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1536 "#ifdef USESHADOWMAPORTHO\n"
1537 " ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1540 "#ifdef USEREFLECTION\n"
1541 " ModelViewProjectionPosition = gl_Position;\n"
1544 "#endif // VERTEX_SHADER\n"
1549 "#ifdef FRAGMENT_SHADER\n"
1550 "#ifdef USEDEFERREDLIGHTMAP\n"
1551 "uniform myhalf2 PixelToScreenTexCoord;\n"
1552 "uniform myhalf3 DeferredMod_Diffuse;\n"
1553 "uniform myhalf3 DeferredMod_Specular;\n"
1555 "uniform myhalf3 Color_Ambient;\n"
1556 "uniform myhalf3 Color_Diffuse;\n"
1557 "uniform myhalf3 Color_Specular;\n"
1558 "uniform myhalf SpecularPower;\n"
1560 "uniform myhalf3 Color_Glow;\n"
1562 "uniform myhalf Alpha;\n"
1563 "#ifdef USEREFLECTION\n"
1564 "uniform vec4 DistortScaleRefractReflect;\n"
1565 "uniform vec4 ScreenScaleRefractReflect;\n"
1566 "uniform vec4 ScreenCenterRefractReflect;\n"
1567 "uniform myhalf4 ReflectColor;\n"
1569 "#ifdef USEREFLECTCUBE\n"
1570 "uniform mat4 ModelToReflectCube;\n"
1571 "uniform sampler2D Texture_ReflectMask;\n"
1572 "uniform samplerCube Texture_ReflectCube;\n"
1574 "#ifdef MODE_LIGHTDIRECTION\n"
1575 "uniform myhalf3 LightColor;\n"
1577 "#ifdef MODE_LIGHTSOURCE\n"
1578 "uniform myhalf3 LightColor;\n"
1582 "#ifdef USEOFFSETMAPPING\n"
1583 " // apply offsetmapping\n"
1584 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1585 "#define TexCoord TexCoordOffset\n"
1588 " // combine the diffuse textures (base, pants, shirt)\n"
1589 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1590 "#ifdef USEALPHAKILL\n"
1591 " if (color.a < 0.5)\n"
1594 " color.a *= Alpha;\n"
1595 "#ifdef USECOLORMAPPING\n"
1596 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1598 "#ifdef USEVERTEXTEXTUREBLEND\n"
1599 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1600 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1601 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1602 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1604 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1607 " // get the surface normal\n"
1608 "#ifdef USEVERTEXTEXTUREBLEND\n"
1609 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1611 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1614 " // get the material colors\n"
1615 " myhalf3 diffusetex = color.rgb;\n"
1616 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1617 "# ifdef USEVERTEXTEXTUREBLEND\n"
1618 " myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1620 " myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1624 "#ifdef USEREFLECTCUBE\n"
1625 " vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1626 " vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1627 " vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1628 " diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1634 "#ifdef MODE_LIGHTSOURCE\n"
1635 " // light source\n"
1636 "#ifdef USEDIFFUSE\n"
1637 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1638 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1639 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1640 "#ifdef USESPECULAR\n"
1641 "#ifdef USEEXACTSPECULARMATH\n"
1642 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1644 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1645 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1647 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1650 " color.rgb = diffusetex * Color_Ambient;\n"
1652 " color.rgb *= LightColor;\n"
1653 " color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1654 "#if defined(USESHADOWMAP2D)\n"
1655 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1657 "# ifdef USECUBEFILTER\n"
1658 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1660 "#endif // MODE_LIGHTSOURCE\n"
1665 "#ifdef MODE_LIGHTDIRECTION\n"
1667 "#ifdef USEDIFFUSE\n"
1668 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1670 "#define lightcolor LightColor\n"
1671 "#endif // MODE_LIGHTDIRECTION\n"
1672 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1674 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1675 " myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1676 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1677 " // convert modelspace light vector to tangentspace\n"
1678 " myhalf3 lightnormal;\n"
1679 " lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1680 " lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1681 " lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1682 " lightnormal = normalize(lightnormal); // VectorS/T/R are not always perfectly normalized, and EXACTSPECULARMATH is very picky about this\n"
1683 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1684 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1685 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1686 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1687 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1688 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1689 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1690 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1691 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1692 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1693 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1694 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1696 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1697 " myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1698 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1704 "#ifdef MODE_FAKELIGHT\n"
1706 "myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
1707 "myhalf3 lightcolor = myhalf3(1.0);\n"
1708 "#endif // MODE_FAKELIGHT\n"
1713 "#ifdef MODE_LIGHTMAP\n"
1714 " color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1715 "#endif // MODE_LIGHTMAP\n"
1716 "#ifdef MODE_VERTEXCOLOR\n"
1717 " color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1718 "#endif // MODE_VERTEXCOLOR\n"
1719 "#ifdef MODE_FLATCOLOR\n"
1720 " color.rgb = diffusetex * Color_Ambient;\n"
1721 "#endif // MODE_FLATCOLOR\n"
1727 "# ifdef USEDIFFUSE\n"
1728 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1729 "# ifdef USESPECULAR\n"
1730 "# ifdef USEEXACTSPECULARMATH\n"
1731 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1733 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1734 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1736 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1738 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1741 " color.rgb = diffusetex * Color_Ambient;\n"
1745 "#ifdef USESHADOWMAPORTHO\n"
1746 " color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1749 "#ifdef USEDEFERREDLIGHTMAP\n"
1750 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1751 " color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1752 " color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1756 "#ifdef USEVERTEXTEXTUREBLEND\n"
1757 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1759 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1764 " color.rgb = FogVertex(color.rgb);\n"
1767 " // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
1768 "#ifdef USEREFLECTION\n"
1769 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1770 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1771 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1772 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1773 " // FIXME temporary hack to detect the case that the reflection\n"
1774 " // gets blackened at edges due to leaving the area that contains actual\n"
1776 " // Remove this 'ack once we have a better way to stop this thing from\n"
1778 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1779 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1780 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1781 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1782 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1783 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1786 " gl_FragColor = vec4(color);\n"
1788 "#endif // FRAGMENT_SHADER\n"
1790 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1791 "#endif // !MODE_DEFERREDGEOMETRY\n"
1792 "#endif // !MODE_WATER\n"
1793 "#endif // !MODE_REFRACTION\n"
1794 "#endif // !MODE_BLOOMBLUR\n"
1795 "#endif // !MODE_GENERIC\n"
1796 "#endif // !MODE_POSTPROCESS\n"
1797 "#endif // !MODE_SHOWDEPTH\n"
1798 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1802 =========================================================================================================================================================
1806 =========================================================================================================================================================
1810 =========================================================================================================================================================
1814 =========================================================================================================================================================
1818 =========================================================================================================================================================
1822 =========================================================================================================================================================
1826 =========================================================================================================================================================
1829 const char *builtincgshaderstring =
1830 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1831 "// written by Forest 'LordHavoc' Hale\n"
1832 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1834 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1835 "#if defined(USEREFLECTION)\n"
1836 "#undef USESHADOWMAPORTHO\n"
1839 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1842 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1843 "#define USELIGHTMAP\n"
1845 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
1846 "#define USEEYEVECTOR\n"
1849 "#ifdef FRAGMENT_SHADER\n"
1851 "//#undef USESHADOWMAPPCF\n"
1852 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1853 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1855 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1859 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1860 "#ifdef VERTEX_SHADER\n"
1863 "float4 gl_Vertex : POSITION,\n"
1864 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1865 "out float4 gl_Position : POSITION,\n"
1866 "out float Depth : TEXCOORD0\n"
1869 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1870 " Depth = gl_Position.z;\n"
1874 "#ifdef FRAGMENT_SHADER\n"
1877 "float Depth : TEXCOORD0,\n"
1878 "out float4 gl_FragColor : COLOR\n"
1881 "// float4 temp = float4(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0),0.0);\n"
1882 " float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
1883 " temp.yz -= floor(temp.yz);\n"
1884 " gl_FragColor = temp;\n"
1885 "// gl_FragColor = float4(Depth,0,0,0);\n"
1888 "#else // !MODE_DEPTH_ORSHADOW\n"
1893 "#ifdef MODE_SHOWDEPTH\n"
1894 "#ifdef VERTEX_SHADER\n"
1897 "float4 gl_Vertex : POSITION,\n"
1898 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1899 "out float4 gl_Position : POSITION,\n"
1900 "out float4 gl_FrontColor : COLOR0\n"
1903 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1904 " gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1908 "#ifdef FRAGMENT_SHADER\n"
1911 "float4 gl_FrontColor : COLOR0,\n"
1912 "out float4 gl_FragColor : COLOR\n"
1915 " gl_FragColor = gl_FrontColor;\n"
1918 "#else // !MODE_SHOWDEPTH\n"
1923 "#ifdef MODE_POSTPROCESS\n"
1925 "#ifdef VERTEX_SHADER\n"
1928 "float4 gl_Vertex : POSITION,\n"
1929 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1930 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1931 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1932 "out float4 gl_Position : POSITION,\n"
1933 "out float2 TexCoord1 : TEXCOORD0,\n"
1934 "out float2 TexCoord2 : TEXCOORD1\n"
1937 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1938 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
1940 " TexCoord2 = gl_MultiTexCoord4.xy;\n"
1945 "#ifdef FRAGMENT_SHADER\n"
1948 "float2 TexCoord1 : TEXCOORD0,\n"
1949 "float2 TexCoord2 : TEXCOORD1,\n"
1950 "uniform sampler Texture_First : register(s0),\n"
1952 "uniform sampler Texture_Second : register(s1),\n"
1954 "#ifdef USEGAMMARAMPS\n"
1955 "uniform sampler Texture_GammaRamps : register(s2),\n"
1957 "#ifdef USESATURATION\n"
1958 "uniform float Saturation : register(c30),\n"
1960 "#ifdef USEVIEWTINT\n"
1961 "uniform float4 ViewTintColor : register(c41),\n"
1963 "uniform float4 UserVec1 : register(c37),\n"
1964 "uniform float4 UserVec2 : register(c38),\n"
1965 "uniform float4 UserVec3 : register(c39),\n"
1966 "uniform float4 UserVec4 : register(c40),\n"
1967 "uniform float ClientTime : register(c2),\n"
1968 "uniform float2 PixelSize : register(c25),\n"
1969 "uniform float4 BloomColorSubtract : register(c43),\n"
1970 "out float4 gl_FragColor : COLOR\n"
1973 " gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1975 " gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
1977 "#ifdef USEVIEWTINT\n"
1978 " gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1981 "#ifdef USEPOSTPROCESSING\n"
1982 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1983 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
1984 " float sobel = 1.0;\n"
1985 " // float2 ts = textureSize(Texture_First, 0);\n"
1986 " // float2 px = float2(1/ts.x, 1/ts.y);\n"
1987 " float2 px = PixelSize;\n"
1988 " float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1989 " float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x, 0.0)).rgb;\n"
1990 " float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1991 " float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1992 " float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x, 0.0)).rgb;\n"
1993 " float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1994 " float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1995 " float3 y2 = tex2D(Texture_First, TexCoord1 + float2( 0.0,-px.y)).rgb;\n"
1996 " float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1997 " float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1998 " float3 y5 = tex2D(Texture_First, TexCoord1 + float2( 0.0, px.y)).rgb;\n"
1999 " float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2000 " float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
2001 " float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
2002 " float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
2003 " float px4 = 1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
2004 " float px5 = 2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
2005 " float px6 = 1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
2006 " float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
2007 " float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
2008 " float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
2009 " float py4 = 1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
2010 " float py5 = 2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
2011 " float py6 = 1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
2012 " sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
2013 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2014 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2015 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2016 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107, 0.707107)) * UserVec1.y;\n"
2017 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990, 0.891007)) * UserVec1.y;\n"
2018 " gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2019 " gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2022 "#ifdef USESATURATION\n"
2023 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2024 " float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2025 " // 'vampire sight' effect, wheres red is compensated\n"
2026 " #ifdef SATURATION_REDCOMPENSATE\n"
2027 " float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
2028 " gl_FragColor.rgb = mix(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2029 " gl_FragColor.r += r;\n"
2031 " // normal desaturation\n"
2032 " //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2033 " gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2037 "#ifdef USEGAMMARAMPS\n"
2038 " gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2039 " gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2040 " gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2044 "#else // !MODE_POSTPROCESS\n"
2049 "#ifdef MODE_GENERIC\n"
2050 "#ifdef VERTEX_SHADER\n"
2053 "float4 gl_Vertex : POSITION,\n"
2054 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2055 "float4 gl_Color : COLOR0,\n"
2056 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2057 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2058 "out float4 gl_Position : POSITION,\n"
2059 "#ifdef USEDIFFUSE\n"
2060 "out float2 TexCoord1 : TEXCOORD0,\n"
2062 "#ifdef USESPECULAR\n"
2063 "out float2 TexCoord2 : TEXCOORD1,\n"
2065 "out float4 gl_FrontColor : COLOR\n"
2069 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2071 " gl_FrontColor = gl_Color; // Cg is forward\n"
2073 "#ifdef USEDIFFUSE\n"
2074 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
2076 "#ifdef USESPECULAR\n"
2077 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
2079 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2083 "#ifdef FRAGMENT_SHADER\n"
2087 "float4 gl_FrontColor : COLOR0,\n"
2088 "float2 TexCoord1 : TEXCOORD0,\n"
2089 "float2 TexCoord2 : TEXCOORD1,\n"
2090 "#ifdef USEDIFFUSE\n"
2091 "uniform sampler Texture_First : register(s0),\n"
2093 "#ifdef USESPECULAR\n"
2094 "uniform sampler Texture_Second : register(s1),\n"
2096 "out float4 gl_FragColor : COLOR\n"
2099 "#ifdef USEVIEWTINT\n"
2100 " gl_FragColor = gl_FrontColor;\n"
2102 " gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
2104 "#ifdef USEDIFFUSE\n"
2105 " gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2108 "#ifdef USESPECULAR\n"
2109 " float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2110 "# ifdef USECOLORMAPPING\n"
2111 " gl_FragColor *= tex2;\n"
2114 " gl_FragColor += tex2;\n"
2116 "# ifdef USEVERTEXTEXTUREBLEND\n"
2117 " gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2122 "#else // !MODE_GENERIC\n"
2127 "#ifdef MODE_BLOOMBLUR\n"
2128 "#ifdef VERTEX_SHADER\n"
2131 "float4 gl_Vertex : POSITION,\n"
2132 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2133 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2134 "out float4 gl_Position : POSITION,\n"
2135 "out float2 TexCoord : TEXCOORD0\n"
2138 " TexCoord = gl_MultiTexCoord0.xy;\n"
2139 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2143 "#ifdef FRAGMENT_SHADER\n"
2147 "float2 TexCoord : TEXCOORD0,\n"
2148 "uniform sampler Texture_First : register(s0),\n"
2149 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2150 "out float4 gl_FragColor : COLOR\n"
2154 " float2 tc = TexCoord;\n"
2155 " float3 color = tex2D(Texture_First, tc).rgb;\n"
2156 " tc += BloomBlur_Parameters.xy;\n"
2157 " for (i = 1;i < SAMPLES;i++)\n"
2159 " color += tex2D(Texture_First, tc).rgb;\n"
2160 " tc += BloomBlur_Parameters.xy;\n"
2162 " gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2165 "#else // !MODE_BLOOMBLUR\n"
2166 "#ifdef MODE_REFRACTION\n"
2167 "#ifdef VERTEX_SHADER\n"
2170 "float4 gl_Vertex : POSITION,\n"
2171 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2172 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2173 "uniform float4x4 TexMatrix : register(c0),\n"
2174 "uniform float3 EyePosition : register(c24),\n"
2175 "out float4 gl_Position : POSITION,\n"
2176 "out float2 TexCoord : TEXCOORD0,\n"
2177 "out float3 EyeVector : TEXCOORD1,\n"
2178 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2181 " TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2182 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2183 " ModelViewProjectionPosition = gl_Position;\n"
2187 "#ifdef FRAGMENT_SHADER\n"
2190 "float2 TexCoord : TEXCOORD0,\n"
2191 "float3 EyeVector : TEXCOORD1,\n"
2192 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2193 "uniform sampler Texture_Normal : register(s0),\n"
2194 "uniform sampler Texture_Refraction : register(s3),\n"
2195 "uniform sampler Texture_Reflection : register(s7),\n"
2196 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2197 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2198 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2199 "uniform float4 RefractColor : register(c29),\n"
2200 "out float4 gl_FragColor : COLOR\n"
2203 " float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2204 " //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2205 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2206 " float2 ScreenTexCoord = SafeScreenTexCoord + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy;\n"
2207 " // FIXME temporary hack to detect the case that the reflection\n"
2208 " // gets blackened at edges due to leaving the area that contains actual\n"
2210 " // Remove this 'ack once we have a better way to stop this thing from\n"
2212 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2213 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2214 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2215 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2216 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2217 " gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
2220 "#else // !MODE_REFRACTION\n"
2225 "#ifdef MODE_WATER\n"
2226 "#ifdef VERTEX_SHADER\n"
2230 "float4 gl_Vertex : POSITION,\n"
2231 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2232 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2233 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2234 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2235 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2236 "uniform float4x4 TexMatrix : register(c0),\n"
2237 "uniform float3 EyePosition : register(c24),\n"
2238 "out float4 gl_Position : POSITION,\n"
2239 "out float2 TexCoord : TEXCOORD0,\n"
2240 "out float3 EyeVector : TEXCOORD1,\n"
2241 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2244 " TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2245 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2246 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2247 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2248 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2249 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2250 " ModelViewProjectionPosition = gl_Position;\n"
2254 "#ifdef FRAGMENT_SHADER\n"
2257 "float2 TexCoord : TEXCOORD0,\n"
2258 "float3 EyeVector : TEXCOORD1,\n"
2259 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2260 "uniform sampler Texture_Normal : register(s0),\n"
2261 "uniform sampler Texture_Refraction : register(s3),\n"
2262 "uniform sampler Texture_Reflection : register(s7),\n"
2263 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2264 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2265 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2266 "uniform float4 RefractColor : register(c29),\n"
2267 "uniform float4 ReflectColor : register(c26),\n"
2268 "uniform float ReflectFactor : register(c27),\n"
2269 "uniform float ReflectOffset : register(c28),\n"
2270 "out float4 gl_FragColor : COLOR\n"
2273 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2274 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2275 " float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2276 " //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2277 " float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2278 " // FIXME temporary hack to detect the case that the reflection\n"
2279 " // gets blackened at edges due to leaving the area that contains actual\n"
2281 " // Remove this 'ack once we have a better way to stop this thing from\n"
2283 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2284 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2285 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2286 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2287 " ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2288 " f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2289 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2290 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2291 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2292 " ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2293 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2294 " gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
2297 "#else // !MODE_WATER\n"
2302 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
2304 "// fragment shader specific:\n"
2305 "#ifdef FRAGMENT_SHADER\n"
2308 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2311 "#ifdef USEFOGHEIGHTTEXTURE\n"
2312 " float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2313 " fogfrac = fogheightpixel.a;\n"
2314 " return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2316 "# ifdef USEFOGOUTSIDE\n"
2317 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2319 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2321 " return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2326 "#ifdef USEOFFSETMAPPING\n"
2327 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2329 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2330 " // 14 sample relief mapping: linear search and then binary search\n"
2331 " // this basically steps forward a small amount repeatedly until it finds\n"
2332 " // itself inside solid, then jitters forward and back using decreasing\n"
2333 " // amounts to find the impact\n"
2334 " //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2335 " //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2336 " float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2337 " float3 RT = float3(TexCoord, 1);\n"
2338 " OffsetVector *= 0.1;\n"
2339 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2340 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2341 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2342 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2343 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2344 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2345 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2346 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2347 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2348 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
2349 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
2350 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
2351 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
2352 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2355 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2356 " // this basically moves forward the full distance, and then backs up based\n"
2357 " // on height of samples\n"
2358 " //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2359 " //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2360 " float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2361 " TexCoord += OffsetVector;\n"
2362 " OffsetVector *= 0.333;\n"
2363 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2364 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2365 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2366 " return TexCoord;\n"
2369 "#endif // USEOFFSETMAPPING\n"
2371 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2372 "#if defined(USESHADOWMAP2D)\n"
2373 "# ifdef USESHADOWMAPORTHO\n"
2374 "# define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2376 "# ifdef USESHADOWMAPVSDCT\n"
2377 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2379 " float3 adir = abs(dir);\n"
2380 " float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2381 " float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2382 " return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2385 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2387 " float3 adir = abs(dir);\n"
2388 " float ma = adir.z;\n"
2389 " float4 proj = float4(dir, 2.5);\n"
2390 " if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2391 " if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2393 " return float3(proj.xy * ShadowMap_Parameters.x / ma + float2(0.5,0.5) + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, ma + 64 * ShadowMap_Parameters.w);\n"
2395 " float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2396 " return float3(proj.xy * aparams.x + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2401 "#endif // defined(USESHADOWMAP2D)\n"
2403 "# ifdef USESHADOWMAP2D\n"
2404 "#ifdef USESHADOWMAPVSDCT\n"
2405 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2407 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2410 "#ifdef USESHADOWMAPVSDCT\n"
2411 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2413 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2417 "# ifdef USESHADOWSAMPLER\n"
2418 "# ifdef USESHADOWMAPPCF\n"
2419 "# define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r \n"
2420 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2421 " f = dot(float4(0.25,0.25,0.25,0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2423 " f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2426 "# ifdef USESHADOWMAPPCF\n"
2427 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2428 "# ifdef GL_ARB_texture_gather\n"
2429 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2431 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2433 " float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2434 "# if USESHADOWMAPPCF > 1\n"
2435 " float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2436 " float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2437 " float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2438 " float4 group4 = step(shadowmaptc.z, texval(-2.0, 0.0));\n"
2439 " float4 group5 = step(shadowmaptc.z, texval( 0.0, 0.0));\n"
2440 " float4 group6 = step(shadowmaptc.z, texval( 2.0, 0.0));\n"
2441 " float4 group7 = step(shadowmaptc.z, texval(-2.0, 2.0));\n"
2442 " float4 group8 = step(shadowmaptc.z, texval( 0.0, 2.0));\n"
2443 " float4 group9 = step(shadowmaptc.z, texval( 2.0, 2.0));\n"
2444 " float4 locols = float4(group1.ab, group3.ab);\n"
2445 " float4 hicols = float4(group7.rg, group9.rg);\n"
2446 " locols.yz += group2.ab;\n"
2447 " hicols.yz += group8.rg;\n"
2448 " float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2449 " float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2450 " lerp(locols, hicols, offset.y);\n"
2451 " float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2452 " cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2453 " f = dot(cols, float4(1.0/25.0));\n"
2455 " float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2456 " float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2457 " float4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
2458 " float4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
2459 " float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2460 " lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2461 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2464 "# ifdef GL_EXT_gpu_shader4\n"
2465 "# define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2467 "# define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r \n"
2469 "# if USESHADOWMAPPCF > 1\n"
2470 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2471 " center *= ShadowMap_TextureScale;\n"
2472 " float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
2473 " float4 row2 = step(shadowmaptc.z, float4(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0), texval( 2.0, 0.0)));\n"
2474 " float4 row3 = step(shadowmaptc.z, float4(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0), texval( 2.0, 1.0)));\n"
2475 " float4 row4 = step(shadowmaptc.z, float4(texval(-1.0, 2.0), texval( 0.0, 2.0), texval( 1.0, 2.0), texval( 2.0, 2.0)));\n"
2476 " float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2477 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2479 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2480 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2481 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2482 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2483 " float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2484 " f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2488 " f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2491 "# ifdef USESHADOWMAPORTHO\n"
2492 " return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2498 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2499 "#endif // FRAGMENT_SHADER\n"
2504 "#ifdef MODE_DEFERREDGEOMETRY\n"
2505 "#ifdef VERTEX_SHADER\n"
2508 "float4 gl_Vertex : POSITION,\n"
2509 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2510 "#ifdef USEVERTEXTEXTUREBLEND\n"
2511 "float4 gl_Color : COLOR0,\n"
2513 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2514 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2515 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2516 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2517 "uniform float4x4 TexMatrix : register(c0),\n"
2518 "#ifdef USEVERTEXTEXTUREBLEND\n"
2519 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2521 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2522 "#ifdef USEOFFSETMAPPING\n"
2523 "uniform float3 EyePosition : register(c24),\n"
2525 "out float4 gl_Position : POSITION,\n"
2526 "#ifdef USEVERTEXTEXTUREBLEND\n"
2527 "out float4 gl_FrontColor : COLOR,\n"
2529 "out float4 TexCoordBoth : TEXCOORD0,\n"
2530 "#ifdef USEOFFSETMAPPING\n"
2531 "out float3 EyeVector : TEXCOORD2,\n"
2533 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2534 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2535 "out float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\n"
2538 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2539 "#ifdef USEVERTEXTEXTUREBLEND\n"
2541 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2543 " gl_FrontColor = gl_Color; // Cg is forward\n"
2545 " TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2548 " // transform unnormalized eye direction into tangent space\n"
2549 "#ifdef USEOFFSETMAPPING\n"
2550 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2551 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2552 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2553 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2556 " VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2557 " VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2558 " VectorR.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2559 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2560 " VectorR.w = gl_Position.z;\n"
2562 "#endif // VERTEX_SHADER\n"
2564 "#ifdef FRAGMENT_SHADER\n"
2567 "float4 TexCoordBoth : TEXCOORD0,\n"
2568 "float3 EyeVector : TEXCOORD2,\n"
2569 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2570 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2571 "float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
2572 "uniform sampler Texture_Normal : register(s0),\n"
2573 "#ifdef USEALPHAKILL\n"
2574 "uniform sampler Texture_Color : register(s1),\n"
2576 "uniform sampler Texture_Gloss : register(s2),\n"
2577 "#ifdef USEVERTEXTEXTUREBLEND\n"
2578 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2579 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2581 "#ifdef USEOFFSETMAPPING\n"
2582 "uniform float OffsetMapping_Scale : register(c24),\n"
2584 "uniform half SpecularPower : register(c36),\n"
2586 "out float4 gl_FragData0 : COLOR0,\n"
2587 "out float4 gl_FragData1 : COLOR1\n"
2589 "out float4 gl_FragColor : COLOR\n"
2593 " float2 TexCoord = TexCoordBoth.xy;\n"
2594 "#ifdef USEOFFSETMAPPING\n"
2595 " // apply offsetmapping\n"
2596 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2597 "#define TexCoord TexCoordOffset\n"
2600 "#ifdef USEALPHAKILL\n"
2601 " if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2605 "#ifdef USEVERTEXTEXTUREBLEND\n"
2606 " float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2607 " float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2608 " //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2609 " //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2612 "#ifdef USEVERTEXTEXTUREBLEND\n"
2613 " float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2614 " float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2616 " float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2617 " float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2621 " gl_FragData0 = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR.xyz) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2622 " float Depth = VectorR.w / 256.0;\n"
2623 " float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
2624 "// float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
2625 " depthcolor.yz -= floor(depthcolor.yz);\n"
2626 " gl_FragData1 = depthcolor;\n"
2628 " gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2631 "#endif // FRAGMENT_SHADER\n"
2632 "#else // !MODE_DEFERREDGEOMETRY\n"
2637 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2638 "#ifdef VERTEX_SHADER\n"
2641 "float4 gl_Vertex : POSITION,\n"
2642 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2643 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2644 "out float4 gl_Position : POSITION,\n"
2645 "out float4 ModelViewPosition : TEXCOORD0\n"
2648 " ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2649 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2651 "#endif // VERTEX_SHADER\n"
2653 "#ifdef FRAGMENT_SHADER\n"
2657 "float2 Pixel : VPOS,\n"
2659 "float2 Pixel : WPOS,\n"
2661 "float4 ModelViewPosition : TEXCOORD0,\n"
2662 "uniform float4x4 ViewToLight : register(c44),\n"
2663 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2664 "uniform float3 LightPosition : register(c23),\n"
2665 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2666 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2667 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2668 "#ifdef USESPECULAR\n"
2669 "uniform half3 DeferredColor_Specular : register(c11),\n"
2670 "uniform half SpecularPower : register(c36),\n"
2672 "uniform sampler Texture_Attenuation : register(s9),\n"
2673 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2674 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2676 "#ifdef USECUBEFILTER\n"
2677 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2680 "#ifdef USESHADOWMAP2D\n"
2681 "# ifdef USESHADOWSAMPLER\n"
2682 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2684 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2688 "#ifdef USESHADOWMAPVSDCT\n"
2689 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2692 "#if defined(USESHADOWMAP2D)\n"
2693 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2694 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2697 "out float4 gl_FragData0 : COLOR0,\n"
2698 "out float4 gl_FragData1 : COLOR1\n"
2701 " // calculate viewspace pixel position\n"
2702 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2703 " //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2704 " float3 position;\n"
2706 " position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
2708 " position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2710 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2711 " // decode viewspace pixel normal\n"
2712 " half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2713 " half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2714 " // surfacenormal = pixel normal in viewspace\n"
2715 " // LightVector = pixel to light in viewspace\n"
2716 " // CubeVector = position in lightspace\n"
2717 " // eyevector = pixel to view in viewspace\n"
2718 " float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2719 " half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2720 "#ifdef USEDIFFUSE\n"
2721 " // calculate diffuse shading\n"
2722 " half3 lightnormal = half3(normalize(LightPosition - position));\n"
2723 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2725 "#ifdef USESPECULAR\n"
2726 " // calculate directional shading\n"
2727 " float3 eyevector = position * -1.0;\n"
2728 "# ifdef USEEXACTSPECULARMATH\n"
2729 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
2731 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2732 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
2736 "#if defined(USESHADOWMAP2D)\n"
2737 " fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2738 "#ifdef USESHADOWMAPVSDCT\n"
2739 ", Texture_CubeProjection\n"
2744 "#ifdef USEDIFFUSE\n"
2745 " gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2747 " gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2749 "#ifdef USESPECULAR\n"
2750 " gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2752 " gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2755 "# ifdef USECUBEFILTER\n"
2756 " float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2757 " gl_FragData0.rgb *= cubecolor;\n"
2758 " gl_FragData1.rgb *= cubecolor;\n"
2761 "#endif // FRAGMENT_SHADER\n"
2762 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2767 "#ifdef VERTEX_SHADER\n"
2770 "float4 gl_Vertex : POSITION,\n"
2771 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2772 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2773 "float4 gl_Color : COLOR0,\n"
2775 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2776 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2777 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2778 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2779 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2781 "uniform float3 EyePosition : register(c24),\n"
2782 "uniform float4x4 TexMatrix : register(c0),\n"
2783 "#ifdef USEVERTEXTEXTUREBLEND\n"
2784 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2786 "#ifdef MODE_LIGHTSOURCE\n"
2787 "uniform float4x4 ModelToLight : register(c20),\n"
2789 "#ifdef MODE_LIGHTSOURCE\n"
2790 "uniform float3 LightPosition : register(c27),\n"
2792 "#ifdef MODE_LIGHTDIRECTION\n"
2793 "uniform float3 LightDir : register(c26),\n"
2795 "uniform float4 FogPlane : register(c25),\n"
2796 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2797 "uniform float3 LightPosition : register(c27),\n"
2799 "#ifdef USESHADOWMAPORTHO\n"
2800 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2802 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2803 "out float4 gl_FrontColor : COLOR,\n"
2805 "out float4 TexCoordBoth : TEXCOORD0,\n"
2806 "#ifdef USELIGHTMAP\n"
2807 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2809 "#ifdef USEEYEVECTOR\n"
2810 "out float3 EyeVector : TEXCOORD2,\n"
2812 "#ifdef USEREFLECTION\n"
2813 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2816 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2818 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE) || defined(USEDIFFUSE)\n"
2819 "out float3 LightVector : TEXCOORD1,\n"
2821 "#ifdef MODE_LIGHTSOURCE\n"
2822 "out float3 CubeVector : TEXCOORD3,\n"
2824 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2825 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2826 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2827 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2829 "#ifdef USESHADOWMAPORTHO\n"
2830 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2832 "out float4 gl_Position : POSITION\n"
2835 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2837 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2839 " gl_FrontColor = gl_Color; // Cg is forward\n"
2842 " // copy the surface texcoord\n"
2843 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2844 "#ifdef USEVERTEXTEXTUREBLEND\n"
2845 " TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2847 "#ifdef USELIGHTMAP\n"
2848 " TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2851 "#ifdef MODE_LIGHTSOURCE\n"
2852 " // transform vertex position into light attenuation/cubemap space\n"
2853 " // (-1 to +1 across the light box)\n"
2854 " CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2856 "# ifdef USEDIFFUSE\n"
2857 " // transform unnormalized light direction into tangent space\n"
2858 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
2859 " // normalize it per pixel)\n"
2860 " float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2861 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2862 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2863 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2867 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2868 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2869 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2870 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2873 " // transform unnormalized eye direction into tangent space\n"
2874 "#ifdef USEEYEVECTOR\n"
2875 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2876 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2877 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2878 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2882 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2883 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2886 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2887 " VectorS = gl_MultiTexCoord1.xyz;\n"
2888 " VectorT = gl_MultiTexCoord2.xyz;\n"
2889 " VectorR = gl_MultiTexCoord3.xyz;\n"
2892 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2893 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2895 "#ifdef USESHADOWMAPORTHO\n"
2896 " ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2899 "#ifdef USEREFLECTION\n"
2900 " ModelViewProjectionPosition = gl_Position;\n"
2903 "#endif // VERTEX_SHADER\n"
2908 "#ifdef FRAGMENT_SHADER\n"
2911 "#ifdef USEDEFERREDLIGHTMAP\n"
2913 "float2 Pixel : VPOS,\n"
2915 "float2 Pixel : WPOS,\n"
2918 "float4 gl_FrontColor : COLOR,\n"
2919 "float4 TexCoordBoth : TEXCOORD0,\n"
2920 "#ifdef USELIGHTMAP\n"
2921 "float2 TexCoordLightmap : TEXCOORD1,\n"
2923 "#ifdef USEEYEVECTOR\n"
2924 "float3 EyeVector : TEXCOORD2,\n"
2926 "#ifdef USEREFLECTION\n"
2927 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2930 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2932 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2933 "float3 LightVector : TEXCOORD1,\n"
2935 "#ifdef MODE_LIGHTSOURCE\n"
2936 "float3 CubeVector : TEXCOORD3,\n"
2938 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2939 "float4 ModelViewPosition : TEXCOORD0,\n"
2941 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2942 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2943 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2944 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2946 "#ifdef USESHADOWMAPORTHO\n"
2947 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2950 "uniform sampler Texture_Normal : register(s0),\n"
2951 "uniform sampler Texture_Color : register(s1),\n"
2952 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2953 "uniform sampler Texture_Gloss : register(s2),\n"
2956 "uniform sampler Texture_Glow : register(s3),\n"
2958 "#ifdef USEVERTEXTEXTUREBLEND\n"
2959 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2960 "uniform sampler Texture_SecondaryColor : register(s5),\n"
2961 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2962 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2965 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
2968 "#ifdef USECOLORMAPPING\n"
2969 "uniform sampler Texture_Pants : register(s4),\n"
2970 "uniform sampler Texture_Shirt : register(s7),\n"
2973 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
2974 "uniform sampler Texture_FogMask : register(s8),\n"
2976 "#ifdef USELIGHTMAP\n"
2977 "uniform sampler Texture_Lightmap : register(s9),\n"
2979 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2980 "uniform sampler Texture_Deluxemap : register(s10),\n"
2982 "#ifdef USEREFLECTION\n"
2983 "uniform sampler Texture_Reflection : register(s7),\n"
2986 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2987 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2988 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2990 "#ifdef USEDEFERREDLIGHTMAP\n"
2991 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2992 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2993 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
2994 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
2997 "#ifdef USECOLORMAPPING\n"
2998 "uniform half3 Color_Pants : register(c7),\n"
2999 "uniform half3 Color_Shirt : register(c8),\n"
3002 "uniform float3 FogColor : register(c16),\n"
3003 "uniform float FogRangeRecip : register(c20),\n"
3004 "uniform float FogPlaneViewDist : register(c19),\n"
3005 "uniform float FogHeightFade : register(c17),\n"
3008 "#ifdef USEOFFSETMAPPING\n"
3009 "uniform float OffsetMapping_Scale : register(c24),\n"
3012 "#ifdef USEDEFERREDLIGHTMAP\n"
3013 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
3014 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
3015 "uniform half3 DeferredMod_Specular : register(c13),\n"
3017 "uniform half3 Color_Ambient : register(c3),\n"
3018 "uniform half3 Color_Diffuse : register(c4),\n"
3019 "uniform half3 Color_Specular : register(c5),\n"
3020 "uniform half SpecularPower : register(c36),\n"
3022 "uniform half3 Color_Glow : register(c6),\n"
3024 "uniform half Alpha : register(c0),\n"
3025 "#ifdef USEREFLECTION\n"
3026 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3027 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3028 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3029 "uniform half4 ReflectColor : register(c26),\n"
3031 "#ifdef USEREFLECTCUBE\n"
3032 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3033 "uniform sampler Texture_ReflectMask : register(s5),\n"
3034 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3036 "#ifdef MODE_LIGHTDIRECTION\n"
3037 "uniform half3 LightColor : register(c21),\n"
3039 "#ifdef MODE_LIGHTSOURCE\n"
3040 "uniform half3 LightColor : register(c21),\n"
3043 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3044 "uniform sampler Texture_Attenuation : register(s9),\n"
3045 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3048 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3050 "#ifdef USESHADOWMAP2D\n"
3051 "# ifdef USESHADOWSAMPLER\n"
3052 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3054 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3058 "#ifdef USESHADOWMAPVSDCT\n"
3059 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3062 "#if defined(USESHADOWMAP2D)\n"
3063 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3064 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3066 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3068 "out float4 gl_FragColor : COLOR\n"
3071 " float2 TexCoord = TexCoordBoth.xy;\n"
3072 "#ifdef USEVERTEXTEXTUREBLEND\n"
3073 " float2 TexCoord2 = TexCoordBoth.zw;\n"
3075 "#ifdef USEOFFSETMAPPING\n"
3076 " // apply offsetmapping\n"
3077 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3078 "#define TexCoord TexCoordOffset\n"
3081 " // combine the diffuse textures (base, pants, shirt)\n"
3082 " half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3083 "#ifdef USEALPHAKILL\n"
3084 " if (color.a < 0.5)\n"
3087 " color.a *= Alpha;\n"
3088 "#ifdef USECOLORMAPPING\n"
3089 " color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3091 "#ifdef USEVERTEXTEXTUREBLEND\n"
3092 " half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3093 " //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3094 " //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3095 " color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3097 " //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3100 " // get the surface normal\n"
3101 "#ifdef USEVERTEXTEXTUREBLEND\n"
3102 " half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3104 " half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3107 " // get the material colors\n"
3108 " half3 diffusetex = color.rgb;\n"
3109 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3110 "# ifdef USEVERTEXTEXTUREBLEND\n"
3111 " half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3113 " half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3117 "#ifdef USEREFLECTCUBE\n"
3118 " float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3119 " float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3120 " float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3121 " diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3127 "#ifdef MODE_LIGHTSOURCE\n"
3128 " // light source\n"
3129 "#ifdef USEDIFFUSE\n"
3130 " half3 lightnormal = half3(normalize(LightVector));\n"
3131 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3132 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3133 "#ifdef USESPECULAR\n"
3134 "#ifdef USEEXACTSPECULARMATH\n"
3135 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3137 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3138 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3140 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3143 " color.rgb = diffusetex * Color_Ambient;\n"
3145 " color.rgb *= LightColor;\n"
3146 " color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3147 "#if defined(USESHADOWMAP2D)\n"
3148 " color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3149 "#ifdef USESHADOWMAPVSDCT\n"
3150 ", Texture_CubeProjection\n"
3155 "# ifdef USECUBEFILTER\n"
3156 " color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3159 "#ifdef USESHADOWMAP2D\n"
3160 "#ifdef USESHADOWMAPVSDCT\n"
3161 "// float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3163 "// float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3165 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3166 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3167 "// color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3168 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3169 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3170 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3171 "// color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3172 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3173 "// color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3174 "// color.r = half(shadowmaptc.z);\n"
3175 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3176 "// color.r = half(shadowmaptc.z);\n"
3178 "// color.rgb = abs(CubeVector);\n"
3180 "// color.rgb = half3(1,1,1);\n"
3181 "#endif // MODE_LIGHTSOURCE\n"
3186 "#ifdef MODE_LIGHTDIRECTION\n"
3188 "#ifdef USEDIFFUSE\n"
3189 " half3 lightnormal = half3(normalize(LightVector));\n"
3191 "#define lightcolor LightColor\n"
3192 "#endif // MODE_LIGHTDIRECTION\n"
3193 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3195 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3196 " half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3197 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3198 " // convert modelspace light vector to tangentspace\n"
3199 " half3 lightnormal;\n"
3200 " lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3201 " lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3202 " lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3203 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3204 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3205 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3206 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3207 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3208 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3209 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3210 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3211 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3212 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3213 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3214 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3216 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3217 " half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3218 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3224 "#ifdef MODE_FAKELIGHT\n"
3226 "half3 lightnormal = half3(normalize(EyeVector));\n"
3227 "half3 lightcolor = half3(1.0,1.0,1.0);\n"
3228 "#endif // MODE_FAKELIGHT\n"
3233 "#ifdef MODE_LIGHTMAP\n"
3234 " color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3235 "#endif // MODE_LIGHTMAP\n"
3236 "#ifdef MODE_VERTEXCOLOR\n"
3237 " color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3238 "#endif // MODE_VERTEXCOLOR\n"
3239 "#ifdef MODE_FLATCOLOR\n"
3240 " color.rgb = diffusetex * Color_Ambient;\n"
3241 "#endif // MODE_FLATCOLOR\n"
3247 "# ifdef USEDIFFUSE\n"
3248 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3249 "# ifdef USESPECULAR\n"
3250 "# ifdef USEEXACTSPECULARMATH\n"
3251 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3253 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3254 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3256 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3258 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3261 " color.rgb = diffusetex * Color_Ambient;\n"
3265 "#ifdef USESHADOWMAPORTHO\n"
3266 " color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
3269 "#ifdef USEDEFERREDLIGHTMAP\n"
3270 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3271 " color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3272 " color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3273 "// color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
3274 "// color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
3278 "#ifdef USEVERTEXTEXTUREBLEND\n"
3279 " color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3281 " color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3286 " color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3289 " // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
3290 "#ifdef USEREFLECTION\n"
3291 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3292 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3293 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3294 " float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3295 " // FIXME temporary hack to detect the case that the reflection\n"
3296 " // gets blackened at edges due to leaving the area that contains actual\n"
3298 " // Remove this 'ack once we have a better way to stop this thing from\n"
3300 " float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3301 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3302 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3303 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3304 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3305 " color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3308 " gl_FragColor = float4(color);\n"
3310 "#endif // FRAGMENT_SHADER\n"
3312 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3313 "#endif // !MODE_DEFERREDGEOMETRY\n"
3314 "#endif // !MODE_WATER\n"
3315 "#endif // !MODE_REFRACTION\n"
3316 "#endif // !MODE_BLOOMBLUR\n"
3317 "#endif // !MODE_GENERIC\n"
3318 "#endif // !MODE_POSTPROCESS\n"
3319 "#endif // !MODE_SHOWDEPTH\n"
3320 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3323 char *glslshaderstring = NULL;
3324 char *cgshaderstring = NULL;
3325 char *hlslshaderstring = NULL;
3327 //=======================================================================================================================================================
3329 typedef struct shaderpermutationinfo_s
3331 const char *pretext;
3334 shaderpermutationinfo_t;
3336 typedef struct shadermodeinfo_s
3338 const char *vertexfilename;
3339 const char *geometryfilename;
3340 const char *fragmentfilename;
3341 const char *pretext;
3346 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3347 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3349 {"#define USEDIFFUSE\n", " diffuse"},
3350 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3351 {"#define USEVIEWTINT\n", " viewtint"},
3352 {"#define USECOLORMAPPING\n", " colormapping"},
3353 {"#define USESATURATION\n", " saturation"},
3354 {"#define USEFOGINSIDE\n", " foginside"},
3355 {"#define USEFOGOUTSIDE\n", " fogoutside"},
3356 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3357 {"#define USEGAMMARAMPS\n", " gammaramps"},
3358 {"#define USECUBEFILTER\n", " cubefilter"},
3359 {"#define USEGLOW\n", " glow"},
3360 {"#define USEBLOOM\n", " bloom"},
3361 {"#define USESPECULAR\n", " specular"},
3362 {"#define USEPOSTPROCESSING\n", " postprocessing"},
3363 {"#define USEREFLECTION\n", " reflection"},
3364 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3365 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3366 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3367 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3368 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3369 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3370 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3371 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3372 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3373 {"#define USEALPHAKILL\n", " alphakill"},
3374 {"#define USEREFLECTCUBE\n", " reflectcube"},
3375 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
3378 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3379 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3381 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3382 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3383 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3384 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3385 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3386 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3387 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3388 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3389 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3390 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3391 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3392 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3393 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3394 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3395 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3396 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3400 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3402 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3403 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3404 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3405 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3406 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3407 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3408 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FAKELIGHT\n", " fakelight"},
3409 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3410 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3411 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3412 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3413 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3414 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3415 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3416 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3417 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3422 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3424 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3425 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3426 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3427 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3428 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3429 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3430 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3431 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3432 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3433 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3434 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3435 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3436 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3437 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3438 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3439 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3443 struct r_glsl_permutation_s;
3444 typedef struct r_glsl_permutation_s
3446 /// hash lookup data
3447 struct r_glsl_permutation_s *hashnext;
3449 unsigned int permutation;
3451 /// indicates if we have tried compiling this permutation already
3453 /// 0 if compilation failed
3455 /// locations of detected uniforms in program object, or -1 if not found
3456 int loc_Texture_First;
3457 int loc_Texture_Second;
3458 int loc_Texture_GammaRamps;
3459 int loc_Texture_Normal;
3460 int loc_Texture_Color;
3461 int loc_Texture_Gloss;
3462 int loc_Texture_Glow;
3463 int loc_Texture_SecondaryNormal;
3464 int loc_Texture_SecondaryColor;
3465 int loc_Texture_SecondaryGloss;
3466 int loc_Texture_SecondaryGlow;
3467 int loc_Texture_Pants;
3468 int loc_Texture_Shirt;
3469 int loc_Texture_FogHeightTexture;
3470 int loc_Texture_FogMask;
3471 int loc_Texture_Lightmap;
3472 int loc_Texture_Deluxemap;
3473 int loc_Texture_Attenuation;
3474 int loc_Texture_Cube;
3475 int loc_Texture_Refraction;
3476 int loc_Texture_Reflection;
3477 int loc_Texture_ShadowMap2D;
3478 int loc_Texture_CubeProjection;
3479 int loc_Texture_ScreenDepth;
3480 int loc_Texture_ScreenNormalMap;
3481 int loc_Texture_ScreenDiffuse;
3482 int loc_Texture_ScreenSpecular;
3483 int loc_Texture_ReflectMask;
3484 int loc_Texture_ReflectCube;
3486 int loc_BloomBlur_Parameters;
3488 int loc_Color_Ambient;
3489 int loc_Color_Diffuse;
3490 int loc_Color_Specular;
3492 int loc_Color_Pants;
3493 int loc_Color_Shirt;
3494 int loc_DeferredColor_Ambient;
3495 int loc_DeferredColor_Diffuse;
3496 int loc_DeferredColor_Specular;
3497 int loc_DeferredMod_Diffuse;
3498 int loc_DeferredMod_Specular;
3499 int loc_DistortScaleRefractReflect;
3500 int loc_EyePosition;
3502 int loc_FogHeightFade;
3504 int loc_FogPlaneViewDist;
3505 int loc_FogRangeRecip;
3508 int loc_LightPosition;
3509 int loc_OffsetMapping_Scale;
3511 int loc_ReflectColor;
3512 int loc_ReflectFactor;
3513 int loc_ReflectOffset;
3514 int loc_RefractColor;
3516 int loc_ScreenCenterRefractReflect;
3517 int loc_ScreenScaleRefractReflect;
3518 int loc_ScreenToDepth;
3519 int loc_ShadowMap_Parameters;
3520 int loc_ShadowMap_TextureScale;
3521 int loc_SpecularPower;
3526 int loc_ViewTintColor;
3527 int loc_ViewToLight;
3528 int loc_ModelToLight;
3530 int loc_BackgroundTexMatrix;
3531 int loc_ModelViewProjectionMatrix;
3532 int loc_ModelViewMatrix;
3533 int loc_PixelToScreenTexCoord;
3534 int loc_ModelToReflectCube;
3535 int loc_ShadowMapMatrix;
3536 int loc_BloomColorSubtract;
3537 int loc_NormalmapScrollBlend;
3539 r_glsl_permutation_t;
3541 #define SHADERPERMUTATION_HASHSIZE 256
3544 // non-degradable "lightweight" shader parameters to keep the permutations simpler
3545 // these can NOT degrade! only use for simple stuff
3548 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
3549 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3550 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
3551 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
3552 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
3553 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5 ///< postprocess uservec4 is enabled
3555 #define SHADERSTATICPARMS_COUNT 6
3557 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
3558 static int shaderstaticparms_count = 0;
3560 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
3561 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
3562 qboolean R_CompileShader_CheckStaticParms(void)
3564 static int r_compileshader_staticparms_save[1];
3565 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
3566 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
3569 if (r_glsl_saturation_redcompensate.integer)
3570 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
3571 if (r_shadow_glossexact.integer)
3572 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
3573 if (r_glsl_postprocess.integer)
3575 if (r_glsl_postprocess_uservec1_enable.integer)
3576 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
3577 if (r_glsl_postprocess_uservec2_enable.integer)
3578 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
3579 if (r_glsl_postprocess_uservec3_enable.integer)
3580 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
3581 if (r_glsl_postprocess_uservec4_enable.integer)
3582 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
3584 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
3587 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
3588 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
3589 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
3591 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
3592 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
3594 shaderstaticparms_count = 0;
3597 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
3598 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
3599 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
3600 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
3601 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
3602 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
3605 /// information about each possible shader permutation
3606 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3607 /// currently selected permutation
3608 r_glsl_permutation_t *r_glsl_permutation;
3609 /// storage for permutations linked in the hash table
3610 memexpandablearray_t r_glsl_permutationarray;
3612 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3614 //unsigned int hashdepth = 0;
3615 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3616 r_glsl_permutation_t *p;
3617 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3619 if (p->mode == mode && p->permutation == permutation)
3621 //if (hashdepth > 10)
3622 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3627 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3629 p->permutation = permutation;
3630 p->hashnext = r_glsl_permutationhash[mode][hashindex];
3631 r_glsl_permutationhash[mode][hashindex] = p;
3632 //if (hashdepth > 10)
3633 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3637 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3640 if (!filename || !filename[0])
3642 if (!strcmp(filename, "glsl/default.glsl"))
3644 if (!glslshaderstring)
3646 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3647 if (glslshaderstring)
3648 Con_DPrintf("Loading shaders from file %s...\n", filename);
3650 glslshaderstring = (char *)builtinshaderstring;
3652 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3653 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3654 return shaderstring;
3656 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3659 if (printfromdisknotice)
3660 Con_DPrintf("from disk %s... ", filename);
3661 return shaderstring;
3663 return shaderstring;
3666 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3669 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3670 char *vertexstring, *geometrystring, *fragmentstring;
3671 char permutationname[256];
3672 int vertstrings_count = 0;
3673 int geomstrings_count = 0;
3674 int fragstrings_count = 0;
3675 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3676 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3677 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3684 permutationname[0] = 0;
3685 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
3686 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3687 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3689 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3691 // the first pretext is which type of shader to compile as
3692 // (later these will all be bound together as a program object)
3693 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3694 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3695 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3697 // the second pretext is the mode (for example a light source)
3698 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3699 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3700 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3701 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3703 // now add all the permutation pretexts
3704 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3706 if (permutation & (1<<i))
3708 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3709 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3710 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3711 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3715 // keep line numbers correct
3716 vertstrings_list[vertstrings_count++] = "\n";
3717 geomstrings_list[geomstrings_count++] = "\n";
3718 fragstrings_list[fragstrings_count++] = "\n";
3723 R_CompileShader_AddStaticParms(mode, permutation);
3724 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3725 vertstrings_count += shaderstaticparms_count;
3726 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3727 geomstrings_count += shaderstaticparms_count;
3728 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3729 fragstrings_count += shaderstaticparms_count;
3731 // now append the shader text itself
3732 vertstrings_list[vertstrings_count++] = vertexstring;
3733 geomstrings_list[geomstrings_count++] = geometrystring;
3734 fragstrings_list[fragstrings_count++] = fragmentstring;
3736 // if any sources were NULL, clear the respective list
3738 vertstrings_count = 0;
3739 if (!geometrystring)
3740 geomstrings_count = 0;
3741 if (!fragmentstring)
3742 fragstrings_count = 0;
3744 // compile the shader program
3745 if (vertstrings_count + geomstrings_count + fragstrings_count)
3746 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3750 qglUseProgramObjectARB(p->program);CHECKGLERROR
3751 // look up all the uniform variable names we care about, so we don't
3752 // have to look them up every time we set them
3754 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
3755 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
3756 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3757 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
3758 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
3759 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3760 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
3761 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3762 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3763 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3764 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3765 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
3766 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3767 p->loc_Texture_FogHeightTexture = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3768 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3769 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3770 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3771 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3772 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
3773 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3774 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3775 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3776 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3777 p->loc_Texture_ScreenDepth = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3778 p->loc_Texture_ScreenNormalMap = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3779 p->loc_Texture_ScreenDiffuse = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3780 p->loc_Texture_ScreenSpecular = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3781 p->loc_Texture_ReflectMask = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3782 p->loc_Texture_ReflectCube = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3783 p->loc_Alpha = qglGetUniformLocationARB(p->program, "Alpha");
3784 p->loc_BloomBlur_Parameters = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3785 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
3786 p->loc_Color_Ambient = qglGetUniformLocationARB(p->program, "Color_Ambient");
3787 p->loc_Color_Diffuse = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3788 p->loc_Color_Specular = qglGetUniformLocationARB(p->program, "Color_Specular");
3789 p->loc_Color_Glow = qglGetUniformLocationARB(p->program, "Color_Glow");
3790 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
3791 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
3792 p->loc_DeferredColor_Ambient = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3793 p->loc_DeferredColor_Diffuse = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3794 p->loc_DeferredColor_Specular = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3795 p->loc_DeferredMod_Diffuse = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3796 p->loc_DeferredMod_Specular = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3797 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3798 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
3799 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
3800 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
3801 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
3802 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3803 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3804 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
3805 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
3806 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
3807 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3808 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
3809 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
3810 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
3811 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
3812 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
3813 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
3814 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3815 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3816 p->loc_ScreenToDepth = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3817 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3818 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3819 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
3820 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
3821 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
3822 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
3823 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
3824 p->loc_ViewTintColor = qglGetUniformLocationARB(p->program, "ViewTintColor");
3825 p->loc_ViewToLight = qglGetUniformLocationARB(p->program, "ViewToLight");
3826 p->loc_ModelToLight = qglGetUniformLocationARB(p->program, "ModelToLight");
3827 p->loc_TexMatrix = qglGetUniformLocationARB(p->program, "TexMatrix");
3828 p->loc_BackgroundTexMatrix = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3829 p->loc_ModelViewMatrix = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3830 p->loc_ModelViewProjectionMatrix = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3831 p->loc_PixelToScreenTexCoord = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3832 p->loc_ModelToReflectCube = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3833 p->loc_ShadowMapMatrix = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3834 p->loc_BloomColorSubtract = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
3835 p->loc_NormalmapScrollBlend = qglGetUniformLocationARB(p->program, "NormalmapScrollBlend");
3836 // initialize the samplers to refer to the texture units we use
3837 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
3838 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
3839 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
3840 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
3841 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
3842 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
3843 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
3844 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3845 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3846 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3847 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
3848 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
3849 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
3850 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3851 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
3852 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
3853 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
3854 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
3855 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
3856 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
3857 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
3858 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
3859 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3860 if (p->loc_Texture_ScreenDepth >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth , GL20TU_SCREENDEPTH);
3861 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3862 if (p->loc_Texture_ScreenDiffuse >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse , GL20TU_SCREENDIFFUSE);
3863 if (p->loc_Texture_ScreenSpecular >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3864 if (p->loc_Texture_ReflectMask >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask , GL20TU_REFLECTMASK);
3865 if (p->loc_Texture_ReflectCube >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube , GL20TU_REFLECTCUBE);
3867 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3870 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
3874 Mem_Free(vertexstring);
3876 Mem_Free(geometrystring);
3878 Mem_Free(fragmentstring);
3881 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3883 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3884 if (r_glsl_permutation != perm)
3886 r_glsl_permutation = perm;
3887 if (!r_glsl_permutation->program)
3889 if (!r_glsl_permutation->compiled)
3890 R_GLSL_CompilePermutation(perm, mode, permutation);
3891 if (!r_glsl_permutation->program)
3893 // remove features until we find a valid permutation
3895 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3897 // reduce i more quickly whenever it would not remove any bits
3898 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3899 if (!(permutation & j))
3902 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3903 if (!r_glsl_permutation->compiled)
3904 R_GLSL_CompilePermutation(perm, mode, permutation);
3905 if (r_glsl_permutation->program)
3908 if (i >= SHADERPERMUTATION_COUNT)
3910 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3911 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3912 qglUseProgramObjectARB(0);CHECKGLERROR
3913 return; // no bit left to clear, entire mode is broken
3918 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3920 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3921 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3922 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3926 #include <Cg/cgGL.h>
3927 struct r_cg_permutation_s;
3928 typedef struct r_cg_permutation_s
3930 /// hash lookup data
3931 struct r_cg_permutation_s *hashnext;
3933 unsigned int permutation;
3935 /// indicates if we have tried compiling this permutation already
3937 /// 0 if compilation failed
3940 /// locations of detected parameters in programs, or NULL if not found
3941 CGparameter vp_EyePosition;
3942 CGparameter vp_FogPlane;
3943 CGparameter vp_LightDir;
3944 CGparameter vp_LightPosition;
3945 CGparameter vp_ModelToLight;
3946 CGparameter vp_TexMatrix;
3947 CGparameter vp_BackgroundTexMatrix;
3948 CGparameter vp_ModelViewProjectionMatrix;
3949 CGparameter vp_ModelViewMatrix;
3950 CGparameter vp_ShadowMapMatrix;
3952 CGparameter fp_Texture_First;
3953 CGparameter fp_Texture_Second;
3954 CGparameter fp_Texture_GammaRamps;
3955 CGparameter fp_Texture_Normal;
3956 CGparameter fp_Texture_Color;
3957 CGparameter fp_Texture_Gloss;
3958 CGparameter fp_Texture_Glow;
3959 CGparameter fp_Texture_SecondaryNormal;
3960 CGparameter fp_Texture_SecondaryColor;
3961 CGparameter fp_Texture_SecondaryGloss;
3962 CGparameter fp_Texture_SecondaryGlow;
3963 CGparameter fp_Texture_Pants;
3964 CGparameter fp_Texture_Shirt;
3965 CGparameter fp_Texture_FogHeightTexture;
3966 CGparameter fp_Texture_FogMask;
3967 CGparameter fp_Texture_Lightmap;
3968 CGparameter fp_Texture_Deluxemap;
3969 CGparameter fp_Texture_Attenuation;
3970 CGparameter fp_Texture_Cube;
3971 CGparameter fp_Texture_Refraction;
3972 CGparameter fp_Texture_Reflection;
3973 CGparameter fp_Texture_ShadowMap2D;
3974 CGparameter fp_Texture_CubeProjection;
3975 CGparameter fp_Texture_ScreenDepth;
3976 CGparameter fp_Texture_ScreenNormalMap;
3977 CGparameter fp_Texture_ScreenDiffuse;
3978 CGparameter fp_Texture_ScreenSpecular;
3979 CGparameter fp_Texture_ReflectMask;
3980 CGparameter fp_Texture_ReflectCube;
3981 CGparameter fp_Alpha;
3982 CGparameter fp_BloomBlur_Parameters;
3983 CGparameter fp_ClientTime;
3984 CGparameter fp_Color_Ambient;
3985 CGparameter fp_Color_Diffuse;
3986 CGparameter fp_Color_Specular;
3987 CGparameter fp_Color_Glow;
3988 CGparameter fp_Color_Pants;
3989 CGparameter fp_Color_Shirt;
3990 CGparameter fp_DeferredColor_Ambient;
3991 CGparameter fp_DeferredColor_Diffuse;
3992 CGparameter fp_DeferredColor_Specular;
3993 CGparameter fp_DeferredMod_Diffuse;
3994 CGparameter fp_DeferredMod_Specular;
3995 CGparameter fp_DistortScaleRefractReflect;
3996 CGparameter fp_EyePosition;
3997 CGparameter fp_FogColor;
3998 CGparameter fp_FogHeightFade;
3999 CGparameter fp_FogPlane;
4000 CGparameter fp_FogPlaneViewDist;
4001 CGparameter fp_FogRangeRecip;
4002 CGparameter fp_LightColor;
4003 CGparameter fp_LightDir;
4004 CGparameter fp_LightPosition;
4005 CGparameter fp_OffsetMapping_Scale;
4006 CGparameter fp_PixelSize;
4007 CGparameter fp_ReflectColor;
4008 CGparameter fp_ReflectFactor;
4009 CGparameter fp_ReflectOffset;
4010 CGparameter fp_RefractColor;
4011 CGparameter fp_Saturation;
4012 CGparameter fp_ScreenCenterRefractReflect;
4013 CGparameter fp_ScreenScaleRefractReflect;
4014 CGparameter fp_ScreenToDepth;
4015 CGparameter fp_ShadowMap_Parameters;
4016 CGparameter fp_ShadowMap_TextureScale;
4017 CGparameter fp_SpecularPower;
4018 CGparameter fp_UserVec1;
4019 CGparameter fp_UserVec2;
4020 CGparameter fp_UserVec3;
4021 CGparameter fp_UserVec4;
4022 CGparameter fp_ViewTintColor;
4023 CGparameter fp_ViewToLight;
4024 CGparameter fp_PixelToScreenTexCoord;
4025 CGparameter fp_ModelToReflectCube;
4026 CGparameter fp_BloomColorSubtract;
4027 CGparameter fp_NormalmapScrollBlend;
4031 /// information about each possible shader permutation
4032 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4033 /// currently selected permutation
4034 r_cg_permutation_t *r_cg_permutation;
4035 /// storage for permutations linked in the hash table
4036 memexpandablearray_t r_cg_permutationarray;
4038 #define CHECKCGERROR {CGerror err = cgGetError(), err2 = err;if (err){Con_Printf("%s:%i CG error %i: %s : %s\n", __FILE__, __LINE__, err, cgGetErrorString(err), cgGetLastErrorString(&err2));if (err == 1) Con_Printf("last listing:\n%s\n", cgGetLastListing(vid.cgcontext));}}
4040 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
4042 //unsigned int hashdepth = 0;
4043 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4044 r_cg_permutation_t *p;
4045 for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4047 if (p->mode == mode && p->permutation == permutation)
4049 //if (hashdepth > 10)
4050 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4055 p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4057 p->permutation = permutation;
4058 p->hashnext = r_cg_permutationhash[mode][hashindex];
4059 r_cg_permutationhash[mode][hashindex] = p;
4060 //if (hashdepth > 10)
4061 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4065 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4068 if (!filename || !filename[0])
4070 if (!strcmp(filename, "cg/default.cg"))
4072 if (!cgshaderstring)
4074 cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4076 Con_DPrintf("Loading shaders from file %s...\n", filename);
4078 cgshaderstring = (char *)builtincgshaderstring;
4080 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4081 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4082 return shaderstring;
4084 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4087 if (printfromdisknotice)
4088 Con_DPrintf("from disk %s... ", filename);
4089 return shaderstring;
4091 return shaderstring;
4094 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4096 // TODO: load or create .fp and .vp shader files
4099 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4102 shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4103 int vertstring_length = 0;
4104 int geomstring_length = 0;
4105 int fragstring_length = 0;
4107 char *vertexstring, *geometrystring, *fragmentstring;
4108 char *vertstring, *geomstring, *fragstring;
4109 char permutationname[256];
4110 char cachename[256];
4111 CGprofile vertexProfile;
4112 CGprofile fragmentProfile;
4113 int vertstrings_count = 0;
4114 int geomstrings_count = 0;
4115 int fragstrings_count = 0;
4116 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4117 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4118 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4126 permutationname[0] = 0;
4128 vertexstring = R_CG_GetText(modeinfo->vertexfilename, true);
4129 geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4130 fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4132 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4133 strlcat(cachename, "cg/", sizeof(cachename));
4135 // the first pretext is which type of shader to compile as
4136 // (later these will all be bound together as a program object)
4137 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4138 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4139 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4141 // the second pretext is the mode (for example a light source)
4142 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4143 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4144 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4145 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4146 strlcat(cachename, modeinfo->name, sizeof(cachename));
4148 // now add all the permutation pretexts
4149 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4151 if (permutation & (1<<i))
4153 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4154 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4155 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4156 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4157 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4161 // keep line numbers correct
4162 vertstrings_list[vertstrings_count++] = "\n";
4163 geomstrings_list[geomstrings_count++] = "\n";
4164 fragstrings_list[fragstrings_count++] = "\n";
4169 R_CompileShader_AddStaticParms(mode, permutation);
4170 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4171 vertstrings_count += shaderstaticparms_count;
4172 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4173 geomstrings_count += shaderstaticparms_count;
4174 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4175 fragstrings_count += shaderstaticparms_count;
4177 // replace spaces in the cachename with _ characters
4178 for (i = 0;cachename[i];i++)
4179 if (cachename[i] == ' ')
4182 // now append the shader text itself
4183 vertstrings_list[vertstrings_count++] = vertexstring;
4184 geomstrings_list[geomstrings_count++] = geometrystring;
4185 fragstrings_list[fragstrings_count++] = fragmentstring;
4187 // if any sources were NULL, clear the respective list
4189 vertstrings_count = 0;
4190 if (!geometrystring)
4191 geomstrings_count = 0;
4192 if (!fragmentstring)
4193 fragstrings_count = 0;
4195 vertstring_length = 0;
4196 for (i = 0;i < vertstrings_count;i++)
4197 vertstring_length += strlen(vertstrings_list[i]);
4198 vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4199 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4200 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4202 geomstring_length = 0;
4203 for (i = 0;i < geomstrings_count;i++)
4204 geomstring_length += strlen(geomstrings_list[i]);
4205 geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4206 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4207 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4209 fragstring_length = 0;
4210 for (i = 0;i < fragstrings_count;i++)
4211 fragstring_length += strlen(fragstrings_list[i]);
4212 fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4213 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4214 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4218 //vertexProfile = CG_PROFILE_ARBVP1;
4219 //fragmentProfile = CG_PROFILE_ARBFP1;
4220 vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4221 fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4222 //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4223 //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4224 //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4227 // try to load the cached shader, or generate one
4228 R_CG_CacheShader(p, cachename, vertstring, fragstring);
4230 // if caching failed, do a dynamic compile for now
4232 if (vertstring[0] && !p->vprogram)
4233 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4235 if (fragstring[0] && !p->fprogram)
4236 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4239 // look up all the uniform variable names we care about, so we don't
4240 // have to look them up every time we set them
4244 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4245 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4246 p->vp_EyePosition = cgGetNamedParameter(p->vprogram, "EyePosition");
4247 p->vp_FogPlane = cgGetNamedParameter(p->vprogram, "FogPlane");
4248 p->vp_LightDir = cgGetNamedParameter(p->vprogram, "LightDir");
4249 p->vp_LightPosition = cgGetNamedParameter(p->vprogram, "LightPosition");
4250 p->vp_ModelToLight = cgGetNamedParameter(p->vprogram, "ModelToLight");
4251 p->vp_TexMatrix = cgGetNamedParameter(p->vprogram, "TexMatrix");
4252 p->vp_BackgroundTexMatrix = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4253 p->vp_ModelViewProjectionMatrix = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4254 p->vp_ModelViewMatrix = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4255 p->vp_ShadowMapMatrix = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4261 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4262 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4263 p->fp_Texture_First = cgGetNamedParameter(p->fprogram, "Texture_First");
4264 p->fp_Texture_Second = cgGetNamedParameter(p->fprogram, "Texture_Second");
4265 p->fp_Texture_GammaRamps = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4266 p->fp_Texture_Normal = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4267 p->fp_Texture_Color = cgGetNamedParameter(p->fprogram, "Texture_Color");
4268 p->fp_Texture_Gloss = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4269 p->fp_Texture_Glow = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4270 p->fp_Texture_SecondaryNormal = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4271 p->fp_Texture_SecondaryColor = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4272 p->fp_Texture_SecondaryGloss = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4273 p->fp_Texture_SecondaryGlow = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4274 p->fp_Texture_Pants = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4275 p->fp_Texture_Shirt = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4276 p->fp_Texture_FogHeightTexture = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4277 p->fp_Texture_FogMask = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4278 p->fp_Texture_Lightmap = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4279 p->fp_Texture_Deluxemap = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4280 p->fp_Texture_Attenuation = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4281 p->fp_Texture_Cube = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4282 p->fp_Texture_Refraction = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4283 p->fp_Texture_Reflection = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4284 p->fp_Texture_ShadowMap2D = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4285 p->fp_Texture_CubeProjection = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4286 p->fp_Texture_ScreenDepth = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4287 p->fp_Texture_ScreenNormalMap = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4288 p->fp_Texture_ScreenDiffuse = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4289 p->fp_Texture_ScreenSpecular = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4290 p->fp_Texture_ReflectMask = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4291 p->fp_Texture_ReflectCube = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4292 p->fp_Alpha = cgGetNamedParameter(p->fprogram, "Alpha");
4293 p->fp_BloomBlur_Parameters = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4294 p->fp_ClientTime = cgGetNamedParameter(p->fprogram, "ClientTime");
4295 p->fp_Color_Ambient = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4296 p->fp_Color_Diffuse = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4297 p->fp_Color_Specular = cgGetNamedParameter(p->fprogram, "Color_Specular");
4298 p->fp_Color_Glow = cgGetNamedParameter(p->fprogram, "Color_Glow");
4299 p->fp_Color_Pants = cgGetNamedParameter(p->fprogram, "Color_Pants");
4300 p->fp_Color_Shirt = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4301 p->fp_DeferredColor_Ambient = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4302 p->fp_DeferredColor_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4303 p->fp_DeferredColor_Specular = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4304 p->fp_DeferredMod_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4305 p->fp_DeferredMod_Specular = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4306 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4307 p->fp_EyePosition = cgGetNamedParameter(p->fprogram, "EyePosition");
4308 p->fp_FogColor = cgGetNamedParameter(p->fprogram, "FogColor");
4309 p->fp_FogHeightFade = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4310 p->fp_FogPlane = cgGetNamedParameter(p->fprogram, "FogPlane");
4311 p->fp_FogPlaneViewDist = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4312 p->fp_FogRangeRecip = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4313 p->fp_LightColor = cgGetNamedParameter(p->fprogram, "LightColor");
4314 p->fp_LightDir = cgGetNamedParameter(p->fprogram, "LightDir");
4315 p->fp_LightPosition = cgGetNamedParameter(p->fprogram, "LightPosition");
4316 p->fp_OffsetMapping_Scale = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4317 p->fp_PixelSize = cgGetNamedParameter(p->fprogram, "PixelSize");
4318 p->fp_ReflectColor = cgGetNamedParameter(p->fprogram, "ReflectColor");
4319 p->fp_ReflectFactor = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4320 p->fp_ReflectOffset = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4321 p->fp_RefractColor = cgGetNamedParameter(p->fprogram, "RefractColor");
4322 p->fp_Saturation = cgGetNamedParameter(p->fprogram, "Saturation");
4323 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4324 p->fp_ScreenScaleRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4325 p->fp_ScreenToDepth = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4326 p->fp_ShadowMap_Parameters = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4327 p->fp_ShadowMap_TextureScale = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4328 p->fp_SpecularPower = cgGetNamedParameter(p->fprogram, "SpecularPower");
4329 p->fp_UserVec1 = cgGetNamedParameter(p->fprogram, "UserVec1");
4330 p->fp_UserVec2 = cgGetNamedParameter(p->fprogram, "UserVec2");
4331 p->fp_UserVec3 = cgGetNamedParameter(p->fprogram, "UserVec3");
4332 p->fp_UserVec4 = cgGetNamedParameter(p->fprogram, "UserVec4");
4333 p->fp_ViewTintColor = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4334 p->fp_ViewToLight = cgGetNamedParameter(p->fprogram, "ViewToLight");
4335 p->fp_PixelToScreenTexCoord = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4336 p->fp_ModelToReflectCube = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4337 p->fp_BloomColorSubtract = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4338 p->fp_NormalmapScrollBlend = cgGetNamedParameter(p->fprogram, "NormalmapScrollBlend");
4342 if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4343 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4345 Con_Printf("^1CG shader %s failed! some features may not work properly.\n", permutationname);
4349 Mem_Free(vertstring);
4351 Mem_Free(geomstring);
4353 Mem_Free(fragstring);
4355 Mem_Free(vertexstring);
4357 Mem_Free(geometrystring);
4359 Mem_Free(fragmentstring);
4362 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4364 r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4367 if (r_cg_permutation != perm)
4369 r_cg_permutation = perm;
4370 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4372 if (!r_cg_permutation->compiled)
4373 R_CG_CompilePermutation(perm, mode, permutation);
4374 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4376 // remove features until we find a valid permutation
4378 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4380 // reduce i more quickly whenever it would not remove any bits
4381 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4382 if (!(permutation & j))
4385 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4386 if (!r_cg_permutation->compiled)
4387 R_CG_CompilePermutation(perm, mode, permutation);
4388 if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4391 if (i >= SHADERPERMUTATION_COUNT)
4393 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4394 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4395 return; // no bit left to clear, entire mode is broken
4401 if (r_cg_permutation->vprogram)
4403 cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4404 cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4405 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4409 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4410 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4412 if (r_cg_permutation->fprogram)
4414 cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4415 cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4416 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4420 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4421 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4425 if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4426 if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4427 if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4430 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4432 cgGLSetTextureParameter(param, R_GetTexture(tex));
4433 cgGLEnableTextureParameter(param);
4441 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4442 extern D3DCAPS9 vid_d3d9caps;
4445 struct r_hlsl_permutation_s;
4446 typedef struct r_hlsl_permutation_s
4448 /// hash lookup data
4449 struct r_hlsl_permutation_s *hashnext;
4451 unsigned int permutation;
4453 /// indicates if we have tried compiling this permutation already
4455 /// NULL if compilation failed
4456 IDirect3DVertexShader9 *vertexshader;
4457 IDirect3DPixelShader9 *pixelshader;
4459 r_hlsl_permutation_t;
4461 typedef enum D3DVSREGISTER_e
4463 D3DVSREGISTER_TexMatrix = 0, // float4x4
4464 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4465 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4466 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4467 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4468 D3DVSREGISTER_ModelToLight = 20, // float4x4
4469 D3DVSREGISTER_EyePosition = 24,
4470 D3DVSREGISTER_FogPlane = 25,
4471 D3DVSREGISTER_LightDir = 26,
4472 D3DVSREGISTER_LightPosition = 27,
4476 typedef enum D3DPSREGISTER_e
4478 D3DPSREGISTER_Alpha = 0,
4479 D3DPSREGISTER_BloomBlur_Parameters = 1,
4480 D3DPSREGISTER_ClientTime = 2,
4481 D3DPSREGISTER_Color_Ambient = 3,
4482 D3DPSREGISTER_Color_Diffuse = 4,
4483 D3DPSREGISTER_Color_Specular = 5,
4484 D3DPSREGISTER_Color_Glow = 6,
4485 D3DPSREGISTER_Color_Pants = 7,
4486 D3DPSREGISTER_Color_Shirt = 8,
4487 D3DPSREGISTER_DeferredColor_Ambient = 9,
4488 D3DPSREGISTER_DeferredColor_Diffuse = 10,
4489 D3DPSREGISTER_DeferredColor_Specular = 11,
4490 D3DPSREGISTER_DeferredMod_Diffuse = 12,
4491 D3DPSREGISTER_DeferredMod_Specular = 13,
4492 D3DPSREGISTER_DistortScaleRefractReflect = 14,
4493 D3DPSREGISTER_EyePosition = 15, // unused
4494 D3DPSREGISTER_FogColor = 16,
4495 D3DPSREGISTER_FogHeightFade = 17,
4496 D3DPSREGISTER_FogPlane = 18,
4497 D3DPSREGISTER_FogPlaneViewDist = 19,
4498 D3DPSREGISTER_FogRangeRecip = 20,
4499 D3DPSREGISTER_LightColor = 21,
4500 D3DPSREGISTER_LightDir = 22, // unused
4501 D3DPSREGISTER_LightPosition = 23,
4502 D3DPSREGISTER_OffsetMapping_Scale = 24,
4503 D3DPSREGISTER_PixelSize = 25,
4504 D3DPSREGISTER_ReflectColor = 26,
4505 D3DPSREGISTER_ReflectFactor = 27,
4506 D3DPSREGISTER_ReflectOffset = 28,
4507 D3DPSREGISTER_RefractColor = 29,
4508 D3DPSREGISTER_Saturation = 30,
4509 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4510 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4511 D3DPSREGISTER_ScreenToDepth = 33,
4512 D3DPSREGISTER_ShadowMap_Parameters = 34,
4513 D3DPSREGISTER_ShadowMap_TextureScale = 35,
4514 D3DPSREGISTER_SpecularPower = 36,
4515 D3DPSREGISTER_UserVec1 = 37,
4516 D3DPSREGISTER_UserVec2 = 38,
4517 D3DPSREGISTER_UserVec3 = 39,
4518 D3DPSREGISTER_UserVec4 = 40,
4519 D3DPSREGISTER_ViewTintColor = 41,
4520 D3DPSREGISTER_PixelToScreenTexCoord = 42,
4521 D3DPSREGISTER_BloomColorSubtract = 43,
4522 D3DPSREGISTER_ViewToLight = 44, // float4x4
4523 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4524 D3DPSREGISTER_NormalmapScrollBlend = 52,
4529 /// information about each possible shader permutation
4530 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4531 /// currently selected permutation
4532 r_hlsl_permutation_t *r_hlsl_permutation;
4533 /// storage for permutations linked in the hash table
4534 memexpandablearray_t r_hlsl_permutationarray;
4536 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4538 //unsigned int hashdepth = 0;
4539 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4540 r_hlsl_permutation_t *p;
4541 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4543 if (p->mode == mode && p->permutation == permutation)
4545 //if (hashdepth > 10)
4546 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4551 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4553 p->permutation = permutation;
4554 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4555 r_hlsl_permutationhash[mode][hashindex] = p;
4556 //if (hashdepth > 10)
4557 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4561 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4564 if (!filename || !filename[0])
4566 if (!strcmp(filename, "hlsl/default.hlsl"))
4568 if (!hlslshaderstring)
4570 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4571 if (hlslshaderstring)
4572 Con_DPrintf("Loading shaders from file %s...\n", filename);
4574 hlslshaderstring = (char *)builtincgshaderstring;
4576 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4577 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4578 return shaderstring;
4580 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4583 if (printfromdisknotice)
4584 Con_DPrintf("from disk %s... ", filename);
4585 return shaderstring;
4587 return shaderstring;
4591 //#include <d3dx9shader.h>
4592 //#include <d3dx9mesh.h>
4594 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4596 DWORD *vsbin = NULL;
4597 DWORD *psbin = NULL;
4598 fs_offset_t vsbinsize;
4599 fs_offset_t psbinsize;
4600 // IDirect3DVertexShader9 *vs = NULL;
4601 // IDirect3DPixelShader9 *ps = NULL;
4602 ID3DXBuffer *vslog = NULL;
4603 ID3DXBuffer *vsbuffer = NULL;
4604 ID3DXConstantTable *vsconstanttable = NULL;
4605 ID3DXBuffer *pslog = NULL;
4606 ID3DXBuffer *psbuffer = NULL;
4607 ID3DXConstantTable *psconstanttable = NULL;
4610 char temp[MAX_INPUTLINE];
4611 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4612 qboolean debugshader = gl_paranoid.integer != 0;
4613 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4614 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4617 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4618 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4620 if ((!vsbin && vertstring) || (!psbin && fragstring))
4622 const char* dllnames_d3dx9 [] =
4646 dllhandle_t d3dx9_dll = NULL;
4647 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4648 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4649 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4650 dllfunction_t d3dx9_dllfuncs[] =
4652 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
4653 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
4654 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
4657 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4659 DWORD shaderflags = 0;
4661 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4662 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4663 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4664 if (vertstring && vertstring[0])
4668 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4669 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4670 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4671 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4674 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4677 vsbinsize = vsbuffer->GetBufferSize();
4678 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4679 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4680 vsbuffer->Release();
4684 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4685 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4689 if (fragstring && fragstring[0])
4693 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4694 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4695 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4696 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4699 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4702 psbinsize = psbuffer->GetBufferSize();
4703 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4704 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4705 psbuffer->Release();
4709 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4710 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4714 Sys_UnloadLibrary(&d3dx9_dll);
4717 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4721 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4722 if (FAILED(vsresult))
4723 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4724 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4725 if (FAILED(psresult))
4726 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4728 // free the shader data
4729 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4730 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4733 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4736 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4737 int vertstring_length = 0;
4738 int geomstring_length = 0;
4739 int fragstring_length = 0;
4741 char *vertexstring, *geometrystring, *fragmentstring;
4742 char *vertstring, *geomstring, *fragstring;
4743 char permutationname[256];
4744 char cachename[256];
4745 int vertstrings_count = 0;
4746 int geomstrings_count = 0;
4747 int fragstrings_count = 0;
4748 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4749 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4750 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4755 p->vertexshader = NULL;
4756 p->pixelshader = NULL;
4758 permutationname[0] = 0;
4760 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
4761 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4762 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4764 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4765 strlcat(cachename, "hlsl/", sizeof(cachename));
4767 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4768 vertstrings_count = 0;
4769 geomstrings_count = 0;
4770 fragstrings_count = 0;
4771 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4772 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4773 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4775 // the first pretext is which type of shader to compile as
4776 // (later these will all be bound together as a program object)
4777 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4778 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4779 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4781 // the second pretext is the mode (for example a light source)
4782 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4783 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4784 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4785 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4786 strlcat(cachename, modeinfo->name, sizeof(cachename));
4788 // now add all the permutation pretexts
4789 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4791 if (permutation & (1<<i))
4793 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4794 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4795 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4796 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4797 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4801 // keep line numbers correct
4802 vertstrings_list[vertstrings_count++] = "\n";
4803 geomstrings_list[geomstrings_count++] = "\n";
4804 fragstrings_list[fragstrings_count++] = "\n";
4809 R_CompileShader_AddStaticParms(mode, permutation);
4810 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4811 vertstrings_count += shaderstaticparms_count;
4812 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4813 geomstrings_count += shaderstaticparms_count;
4814 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4815 fragstrings_count += shaderstaticparms_count;
4817 // replace spaces in the cachename with _ characters
4818 for (i = 0;cachename[i];i++)
4819 if (cachename[i] == ' ')
4822 // now append the shader text itself
4823 vertstrings_list[vertstrings_count++] = vertexstring;
4824 geomstrings_list[geomstrings_count++] = geometrystring;
4825 fragstrings_list[fragstrings_count++] = fragmentstring;
4827 // if any sources were NULL, clear the respective list
4829 vertstrings_count = 0;
4830 if (!geometrystring)
4831 geomstrings_count = 0;
4832 if (!fragmentstring)
4833 fragstrings_count = 0;
4835 vertstring_length = 0;
4836 for (i = 0;i < vertstrings_count;i++)
4837 vertstring_length += strlen(vertstrings_list[i]);
4838 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4839 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4840 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4842 geomstring_length = 0;
4843 for (i = 0;i < geomstrings_count;i++)
4844 geomstring_length += strlen(geomstrings_list[i]);
4845 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4846 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4847 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4849 fragstring_length = 0;
4850 for (i = 0;i < fragstrings_count;i++)
4851 fragstring_length += strlen(fragstrings_list[i]);
4852 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4853 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4854 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4856 // try to load the cached shader, or generate one
4857 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4859 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4860 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4862 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
4866 Mem_Free(vertstring);
4868 Mem_Free(geomstring);
4870 Mem_Free(fragstring);
4872 Mem_Free(vertexstring);
4874 Mem_Free(geometrystring);
4876 Mem_Free(fragmentstring);
4879 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4880 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4881 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4882 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4883 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4884 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4886 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4887 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4888 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4889 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4890 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4891 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4893 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4895 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4896 if (r_hlsl_permutation != perm)
4898 r_hlsl_permutation = perm;
4899 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4901 if (!r_hlsl_permutation->compiled)
4902 R_HLSL_CompilePermutation(perm, mode, permutation);
4903 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4905 // remove features until we find a valid permutation
4907 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4909 // reduce i more quickly whenever it would not remove any bits
4910 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4911 if (!(permutation & j))
4914 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4915 if (!r_hlsl_permutation->compiled)
4916 R_HLSL_CompilePermutation(perm, mode, permutation);
4917 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4920 if (i >= SHADERPERMUTATION_COUNT)
4922 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4923 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4924 return; // no bit left to clear, entire mode is broken
4928 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4929 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4931 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4932 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4933 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4937 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
4939 DPSOFTRAST_SetShader(mode, permutation);
4940 DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
4941 DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
4942 DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
4945 void R_GLSL_Restart_f(void)
4947 unsigned int i, limit;
4948 if (glslshaderstring && glslshaderstring != builtinshaderstring)
4949 Mem_Free(glslshaderstring);
4950 glslshaderstring = NULL;
4951 if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4952 Mem_Free(cgshaderstring);
4953 cgshaderstring = NULL;
4954 if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
4955 Mem_Free(hlslshaderstring);
4956 hlslshaderstring = NULL;
4957 switch(vid.renderpath)
4959 case RENDERPATH_D3D9:
4962 r_hlsl_permutation_t *p;
4963 r_hlsl_permutation = NULL;
4964 // cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4965 // cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4966 // cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4967 // cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4968 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
4969 for (i = 0;i < limit;i++)
4971 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
4973 if (p->vertexshader)
4974 IDirect3DVertexShader9_Release(p->vertexshader);
4976 IDirect3DPixelShader9_Release(p->pixelshader);
4977 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
4980 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4984 case RENDERPATH_D3D10:
4985 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4987 case RENDERPATH_D3D11:
4988 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4990 case RENDERPATH_GL20:
4992 r_glsl_permutation_t *p;
4993 r_glsl_permutation = NULL;
4994 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4995 for (i = 0;i < limit;i++)
4997 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4999 GL_Backend_FreeProgram(p->program);
5000 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
5003 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5006 case RENDERPATH_CGGL:
5009 r_cg_permutation_t *p;
5010 r_cg_permutation = NULL;
5011 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5012 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5013 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5014 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5015 limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
5016 for (i = 0;i < limit;i++)
5018 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
5021 cgDestroyProgram(p->vprogram);
5023 cgDestroyProgram(p->fprogram);
5024 Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
5027 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5031 case RENDERPATH_GL13:
5032 case RENDERPATH_GL11:
5034 case RENDERPATH_SOFT:
5039 void R_GLSL_DumpShader_f(void)
5044 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
5047 FS_Print(file, "/* The engine may define the following macros:\n");
5048 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5049 for (i = 0;i < SHADERMODE_COUNT;i++)
5050 FS_Print(file, glslshadermodeinfo[i].pretext);
5051 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5052 FS_Print(file, shaderpermutationinfo[i].pretext);
5053 FS_Print(file, "*/\n");
5054 FS_Print(file, builtinshaderstring);
5056 Con_Printf("glsl/default.glsl written\n");
5059 Con_Printf("failed to write to glsl/default.glsl\n");
5062 file = FS_OpenRealFile("cg/default.cg", "w", false);
5065 FS_Print(file, "/* The engine may define the following macros:\n");
5066 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5067 for (i = 0;i < SHADERMODE_COUNT;i++)
5068 FS_Print(file, cgshadermodeinfo[i].pretext);
5069 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5070 FS_Print(file, shaderpermutationinfo[i].pretext);
5071 FS_Print(file, "*/\n");
5072 FS_Print(file, builtincgshaderstring);
5074 Con_Printf("cg/default.cg written\n");
5077 Con_Printf("failed to write to cg/default.cg\n");
5081 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
5084 FS_Print(file, "/* The engine may define the following macros:\n");
5085 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5086 for (i = 0;i < SHADERMODE_COUNT;i++)
5087 FS_Print(file, hlslshadermodeinfo[i].pretext);
5088 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5089 FS_Print(file, shaderpermutationinfo[i].pretext);
5090 FS_Print(file, "*/\n");
5091 FS_Print(file, builtincgshaderstring);
5093 Con_Printf("hlsl/default.hlsl written\n");
5096 Con_Printf("failed to write to hlsl/default.hlsl\n");
5100 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
5103 texturemode = GL_MODULATE;
5104 switch (vid.renderpath)
5106 case RENDERPATH_D3D9:
5108 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5109 R_Mesh_TexBind(GL20TU_FIRST , first );
5110 R_Mesh_TexBind(GL20TU_SECOND, second);
5113 case RENDERPATH_D3D10:
5114 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5116 case RENDERPATH_D3D11:
5117 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5119 case RENDERPATH_GL20:
5120 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5121 R_Mesh_TexBind(GL20TU_FIRST , first );
5122 R_Mesh_TexBind(GL20TU_SECOND, second);
5124 case RENDERPATH_CGGL:
5127 R_SetupShader_SetPermutationCG(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5128 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
5129 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
5132 case RENDERPATH_GL13:
5133 R_Mesh_TexBind(0, first );
5134 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
5135 R_Mesh_TexBind(1, second);
5137 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
5139 case RENDERPATH_GL11:
5140 R_Mesh_TexBind(0, first );
5142 case RENDERPATH_SOFT:
5143 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5144 R_Mesh_TexBind(GL20TU_FIRST , first );
5145 R_Mesh_TexBind(GL20TU_SECOND, second);
5150 void R_SetupShader_DepthOrShadow(void)
5152 switch (vid.renderpath)
5154 case RENDERPATH_D3D9:
5156 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5159 case RENDERPATH_D3D10:
5160 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5162 case RENDERPATH_D3D11:
5163 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5165 case RENDERPATH_GL20:
5166 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5168 case RENDERPATH_CGGL:
5170 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5173 case RENDERPATH_GL13:
5174 R_Mesh_TexBind(0, 0);
5175 R_Mesh_TexBind(1, 0);
5177 case RENDERPATH_GL11:
5178 R_Mesh_TexBind(0, 0);
5180 case RENDERPATH_SOFT:
5181 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
5186 void R_SetupShader_ShowDepth(void)
5188 switch (vid.renderpath)
5190 case RENDERPATH_D3D9:
5192 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5195 case RENDERPATH_D3D10:
5196 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5198 case RENDERPATH_D3D11:
5199 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5201 case RENDERPATH_GL20:
5202 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5204 case RENDERPATH_CGGL:
5206 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5209 case RENDERPATH_GL13:
5211 case RENDERPATH_GL11:
5213 case RENDERPATH_SOFT:
5214 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
5219 extern qboolean r_shadow_usingdeferredprepass;
5220 extern cvar_t r_shadow_deferred_8bitrange;
5221 extern rtexture_t *r_shadow_attenuationgradienttexture;
5222 extern rtexture_t *r_shadow_attenuation2dtexture;
5223 extern rtexture_t *r_shadow_attenuation3dtexture;
5224 extern qboolean r_shadow_usingshadowmap2d;
5225 extern qboolean r_shadow_usingshadowmaportho;
5226 extern float r_shadow_shadowmap_texturescale[2];
5227 extern float r_shadow_shadowmap_parameters[4];
5228 extern qboolean r_shadow_shadowmapvsdct;
5229 extern qboolean r_shadow_shadowmapsampler;
5230 extern int r_shadow_shadowmappcf;
5231 extern rtexture_t *r_shadow_shadowmap2dtexture;
5232 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5233 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5234 extern matrix4x4_t r_shadow_shadowmapmatrix;
5235 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5236 extern int r_shadow_prepass_width;
5237 extern int r_shadow_prepass_height;
5238 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5239 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5240 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
5241 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5242 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5243 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5245 // a blendfunc allows colormod if:
5246 // a) it can never keep the destination pixel invariant, or
5247 // b) it can keep the destination pixel invariant, and still can do so if colormodded
5248 // this is to prevent unintended side effects from colormod
5251 // IF there is a (s, sa) for which for all (d, da),
5252 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5253 // THEN, for this (s, sa) and all (colormod, d, da):
5254 // s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5255 // OBVIOUSLY, this means that
5256 // s*colormod * src(s*colormod, d, sa, da) = 0
5257 // dst(s*colormod, d, sa, da) = 1
5259 // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5261 // main condition to leave dst color invariant:
5262 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5264 // s * 0 + d * dst(s, d, sa, da) == d
5265 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5266 // => colormod is a problem for GL_SRC_COLOR only
5268 // s + d * dst(s, d, sa, da) == d
5270 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5271 // => colormod is never problematic for these
5272 // src == GL_SRC_COLOR:
5273 // s*s + d * dst(s, d, sa, da) == d
5275 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5276 // => colormod is never problematic for these
5277 // src == GL_ONE_MINUS_SRC_COLOR:
5278 // s*(1-s) + d * dst(s, d, sa, da) == d
5279 // => s == 0 or s == 1
5280 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5281 // => colormod is a problem for GL_SRC_COLOR only
5282 // src == GL_DST_COLOR
5283 // s*d + d * dst(s, d, sa, da) == d
5285 // => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5286 // => colormod is always a problem
5289 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5290 // => colormod is never problematic for these
5291 // => BUT, we do not know s! We must assume it is problematic
5292 // then... except in GL_ONE case, where we know all invariant
5294 // src == GL_ONE_MINUS_DST_COLOR
5295 // s*(1-d) + d * dst(s, d, sa, da) == d
5296 // => s == 0 (1-d is impossible to handle for our desired result)
5297 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5298 // => colormod is never problematic for these
5299 // src == GL_SRC_ALPHA
5300 // s*sa + d * dst(s, d, sa, da) == d
5301 // => s == 0, or sa == 0
5302 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5303 // => colormod breaks in the case GL_SRC_COLOR only
5304 // src == GL_ONE_MINUS_SRC_ALPHA
5305 // s*(1-sa) + d * dst(s, d, sa, da) == d
5306 // => s == 0, or sa == 1
5307 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5308 // => colormod breaks in the case GL_SRC_COLOR only
5309 // src == GL_DST_ALPHA
5310 // s*da + d * dst(s, d, sa, da) == d
5312 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5313 // => colormod is never problematic for these
5318 case GL_ONE_MINUS_SRC_COLOR:
5320 case GL_ONE_MINUS_SRC_ALPHA:
5321 if(dst == GL_SRC_COLOR)
5326 case GL_ONE_MINUS_DST_COLOR:
5328 case GL_ONE_MINUS_DST_ALPHA:
5338 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane)
5340 // select a permutation of the lighting shader appropriate to this
5341 // combination of texture, entity, light source, and fogging, only use the
5342 // minimum features necessary to avoid wasting rendering time in the
5343 // fragment shader on features that are not being used
5344 unsigned int permutation = 0;
5345 unsigned int mode = 0;
5346 qboolean allow_colormod;
5347 static float dummy_colormod[3] = {1, 1, 1};
5348 float *colormod = rsurface.colormod;
5350 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5351 if (rsurfacepass == RSURFPASS_BACKGROUND)
5353 // distorted background
5354 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5356 mode = SHADERMODE_WATER;
5357 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
5358 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
5359 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
5361 // this is the right thing to do for wateralpha
5362 GL_BlendFunc(GL_ONE, GL_ZERO);
5363 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5367 // this is the right thing to do for entity alpha
5368 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5369 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5372 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5374 mode = SHADERMODE_REFRACTION;
5375 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5376 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5380 mode = SHADERMODE_GENERIC;
5381 permutation |= SHADERPERMUTATION_DIFFUSE;
5382 GL_BlendFunc(GL_ONE, GL_ZERO);
5383 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5385 GL_AlphaTest(false);
5387 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5389 if (r_glsl_offsetmapping.integer)
5391 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5392 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5393 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5394 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5395 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5397 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5398 if (r_glsl_offsetmapping_reliefmapping.integer)
5399 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5402 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5403 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5404 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5405 permutation |= SHADERPERMUTATION_ALPHAKILL;
5406 // normalmap (deferred prepass), may use alpha test on diffuse
5407 mode = SHADERMODE_DEFERREDGEOMETRY;
5408 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5409 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5410 GL_AlphaTest(false);
5411 GL_BlendFunc(GL_ONE, GL_ZERO);
5412 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5414 else if (rsurfacepass == RSURFPASS_RTLIGHT)
5416 if (r_glsl_offsetmapping.integer)
5418 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5419 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5420 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5421 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5422 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5424 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5425 if (r_glsl_offsetmapping_reliefmapping.integer)
5426 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5429 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5430 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5432 mode = SHADERMODE_LIGHTSOURCE;
5433 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5434 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5435 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5436 permutation |= SHADERPERMUTATION_CUBEFILTER;
5437 if (diffusescale > 0)
5438 permutation |= SHADERPERMUTATION_DIFFUSE;
5439 if (specularscale > 0)
5440 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5441 if (r_refdef.fogenabled)
5442 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5443 if (rsurface.texture->colormapping)
5444 permutation |= SHADERPERMUTATION_COLORMAPPING;
5445 if (r_shadow_usingshadowmap2d)
5447 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5448 if(r_shadow_shadowmapvsdct)
5449 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5451 if (r_shadow_shadowmapsampler)
5452 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5453 if (r_shadow_shadowmappcf > 1)
5454 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5455 else if (r_shadow_shadowmappcf)
5456 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5458 if (rsurface.texture->reflectmasktexture)
5459 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5460 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5461 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5462 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5464 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5466 if (r_glsl_offsetmapping.integer)
5468 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5469 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5470 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5471 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5472 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5474 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5475 if (r_glsl_offsetmapping_reliefmapping.integer)
5476 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5479 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5480 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5481 // unshaded geometry (fullbright or ambient model lighting)
5482 mode = SHADERMODE_FLATCOLOR;
5483 ambientscale = diffusescale = specularscale = 0;
5484 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5485 permutation |= SHADERPERMUTATION_GLOW;
5486 if (r_refdef.fogenabled)
5487 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5488 if (rsurface.texture->colormapping)
5489 permutation |= SHADERPERMUTATION_COLORMAPPING;
5490 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5492 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5493 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5495 if (r_shadow_shadowmapsampler)
5496 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5497 if (r_shadow_shadowmappcf > 1)
5498 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5499 else if (r_shadow_shadowmappcf)
5500 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5502 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5503 permutation |= SHADERPERMUTATION_REFLECTION;
5504 if (rsurface.texture->reflectmasktexture)
5505 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5506 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5507 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5508 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5510 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5512 if (r_glsl_offsetmapping.integer)
5514 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5515 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5516 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5517 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5518 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5520 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5521 if (r_glsl_offsetmapping_reliefmapping.integer)
5522 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5525 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5526 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5527 // directional model lighting
5528 mode = SHADERMODE_LIGHTDIRECTION;
5529 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5530 permutation |= SHADERPERMUTATION_GLOW;
5531 permutation |= SHADERPERMUTATION_DIFFUSE;
5532 if (specularscale > 0)
5533 permutation |= SHADERPERMUTATION_SPECULAR;
5534 if (r_refdef.fogenabled)
5535 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5536 if (rsurface.texture->colormapping)
5537 permutation |= SHADERPERMUTATION_COLORMAPPING;
5538 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5540 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5541 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5543 if (r_shadow_shadowmapsampler)
5544 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5545 if (r_shadow_shadowmappcf > 1)
5546 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5547 else if (r_shadow_shadowmappcf)
5548 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5550 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5551 permutation |= SHADERPERMUTATION_REFLECTION;
5552 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5553 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5554 if (rsurface.texture->reflectmasktexture)
5555 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5556 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5557 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5558 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5560 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5562 if (r_glsl_offsetmapping.integer)
5564 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5565 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5566 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5567 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5568 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5570 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5571 if (r_glsl_offsetmapping_reliefmapping.integer)
5572 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5575 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5576 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5577 // ambient model lighting
5578 mode = SHADERMODE_LIGHTDIRECTION;
5579 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5580 permutation |= SHADERPERMUTATION_GLOW;
5581 if (r_refdef.fogenabled)
5582 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5583 if (rsurface.texture->colormapping)
5584 permutation |= SHADERPERMUTATION_COLORMAPPING;
5585 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5587 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5588 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5590 if (r_shadow_shadowmapsampler)
5591 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5592 if (r_shadow_shadowmappcf > 1)
5593 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5594 else if (r_shadow_shadowmappcf)
5595 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5597 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5598 permutation |= SHADERPERMUTATION_REFLECTION;
5599 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5600 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5601 if (rsurface.texture->reflectmasktexture)
5602 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5603 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5604 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5605 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5609 if (r_glsl_offsetmapping.integer)
5611 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5612 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5613 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5614 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5615 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5617 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5618 if (r_glsl_offsetmapping_reliefmapping.integer)
5619 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5622 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5623 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5625 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5626 permutation |= SHADERPERMUTATION_GLOW;
5627 if (r_refdef.fogenabled)
5628 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5629 if (rsurface.texture->colormapping)
5630 permutation |= SHADERPERMUTATION_COLORMAPPING;
5631 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5633 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5634 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5636 if (r_shadow_shadowmapsampler)
5637 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5638 if (r_shadow_shadowmappcf > 1)
5639 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5640 else if (r_shadow_shadowmappcf)
5641 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5643 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5644 permutation |= SHADERPERMUTATION_REFLECTION;
5645 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5646 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5647 if (rsurface.texture->reflectmasktexture)
5648 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5649 if (FAKELIGHT_ENABLED)
5651 // fake lightmapping (q1bsp, q3bsp, fullbright map)
5652 mode = SHADERMODE_FAKELIGHT;
5653 permutation |= SHADERPERMUTATION_DIFFUSE;
5654 if (specularscale > 0)
5655 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5657 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5659 // deluxemapping (light direction texture)
5660 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5661 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5663 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5664 permutation |= SHADERPERMUTATION_DIFFUSE;
5665 if (specularscale > 0)
5666 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5668 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5670 // fake deluxemapping (uniform light direction in tangentspace)
5671 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5672 permutation |= SHADERPERMUTATION_DIFFUSE;
5673 if (specularscale > 0)
5674 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5676 else if (rsurface.uselightmaptexture)
5678 // ordinary lightmapping (q1bsp, q3bsp)
5679 mode = SHADERMODE_LIGHTMAP;
5683 // ordinary vertex coloring (q3bsp)
5684 mode = SHADERMODE_VERTEXCOLOR;
5686 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5687 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5688 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5691 colormod = dummy_colormod;
5692 switch(vid.renderpath)
5694 case RENDERPATH_D3D9:
5696 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
5697 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5698 R_SetupShader_SetPermutationHLSL(mode, permutation);
5699 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5700 if (mode == SHADERMODE_LIGHTSOURCE)
5702 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5703 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5707 if (mode == SHADERMODE_LIGHTDIRECTION)
5709 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5712 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5713 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5714 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5715 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5716 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5718 if (mode == SHADERMODE_LIGHTSOURCE)
5720 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5721 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5722 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5723 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5724 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5726 // additive passes are only darkened by fog, not tinted
5727 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5728 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5732 if (mode == SHADERMODE_FLATCOLOR)
5734 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5736 else if (mode == SHADERMODE_LIGHTDIRECTION)
5738 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
5739 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5740 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
5741 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
5742 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5743 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5744 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5748 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5749 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5750 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
5751 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
5752 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5754 // additive passes are only darkened by fog, not tinted
5755 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5756 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5758 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5759 hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
5760 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5761 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5762 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5763 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5764 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5765 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5766 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5767 if (mode == SHADERMODE_WATER)
5768 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5770 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5771 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5772 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5773 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
5774 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5775 if (rsurface.texture->pantstexture)
5776 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5778 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5779 if (rsurface.texture->shirttexture)
5780 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5782 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5783 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5784 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5785 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5786 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5787 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5788 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5789 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5791 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5792 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5793 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5794 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5795 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5796 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5797 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5798 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5799 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5800 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5801 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5802 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5803 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5804 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5805 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5806 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5807 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5808 if (rsurfacepass == RSURFPASS_BACKGROUND)
5810 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5811 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5812 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5816 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5818 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5819 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5820 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5821 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5822 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5824 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5825 if (rsurface.rtlight)
5827 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5828 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5833 case RENDERPATH_D3D10:
5834 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5836 case RENDERPATH_D3D11:
5837 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5839 case RENDERPATH_GL20:
5840 if (!vid.useinterleavedarrays)
5842 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
5843 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5844 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5845 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5846 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5847 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5848 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5849 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5853 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
5854 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5856 R_SetupShader_SetPermutationGLSL(mode, permutation);
5857 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5858 if (mode == SHADERMODE_LIGHTSOURCE)
5860 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5861 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5862 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5863 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5864 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5865 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5867 // additive passes are only darkened by fog, not tinted
5868 if (r_glsl_permutation->loc_FogColor >= 0)
5869 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5870 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5874 if (mode == SHADERMODE_FLATCOLOR)
5876 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5878 else if (mode == SHADERMODE_LIGHTDIRECTION)
5880 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
5881 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5882 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
5883 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
5884 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5885 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
5886 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5890 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5891 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5892 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
5893 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
5894 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5896 // additive passes are only darkened by fog, not tinted
5897 if (r_glsl_permutation->loc_FogColor >= 0)
5899 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5900 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5902 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5904 if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
5905 if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5906 if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5907 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5908 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5909 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5910 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5911 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5912 if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2fARB(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5914 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5915 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5916 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5917 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2fARB(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5918 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4fARB(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5920 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5921 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
5922 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5923 if (r_glsl_permutation->loc_Color_Pants >= 0)
5925 if (rsurface.texture->pantstexture)
5926 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5928 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5930 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5932 if (rsurface.texture->shirttexture)
5933 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5935 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5937 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4fARB(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5938 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5939 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5940 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5941 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5942 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2fARB(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5943 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5945 // if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_texture_white );
5946 // if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_texture_white );
5947 // if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS , r_texture_gammaramps );
5948 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5949 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5950 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5951 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5952 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5953 if (r_glsl_permutation->loc_Texture_SecondaryColor >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5954 if (r_glsl_permutation->loc_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5955 if (r_glsl_permutation->loc_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5956 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5957 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5958 if (r_glsl_permutation->loc_Texture_ReflectMask >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5959 if (r_glsl_permutation->loc_Texture_ReflectCube >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5960 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5961 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5962 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5963 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5964 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5965 if (rsurfacepass == RSURFPASS_BACKGROUND)
5967 if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5968 else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5969 if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5973 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5975 // if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5976 // if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5977 if (r_glsl_permutation->loc_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5978 if (r_glsl_permutation->loc_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5979 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5981 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture );
5982 if (rsurface.rtlight)
5984 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5985 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5990 case RENDERPATH_CGGL:
5992 if (!vid.useinterleavedarrays)
5994 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
5995 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5996 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5997 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5998 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5999 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
6000 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
6001 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
6005 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
6006 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
6008 R_SetupShader_SetPermutationCG(mode, permutation);
6009 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
6010 if (mode == SHADERMODE_LIGHTSOURCE)
6012 if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
6013 if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6017 if (mode == SHADERMODE_LIGHTDIRECTION)
6019 if (r_cg_permutation->vp_LightDir) cgGLSetParameter3f(r_cg_permutation->vp_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);CHECKCGERROR
6022 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
6023 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
6024 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
6025 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6026 if (r_cg_permutation->vp_FogPlane) cgGLSetParameter4f(r_cg_permutation->vp_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);CHECKCGERROR
6029 if (mode == SHADERMODE_LIGHTSOURCE)
6031 if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6032 if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
6033 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
6034 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
6035 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);CHECKCGERROR
6037 // additive passes are only darkened by fog, not tinted
6038 if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
6039 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6043 if (mode == SHADERMODE_FLATCOLOR)
6045 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
6047 else if (mode == SHADERMODE_LIGHTDIRECTION)
6049 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);CHECKCGERROR
6050 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);CHECKCGERROR
6051 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);CHECKCGERROR
6052 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);CHECKCGERROR
6053 if (r_cg_permutation->fp_DeferredMod_Specular) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
6054 if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);CHECKCGERROR
6055 if (r_cg_permutation->fp_LightDir) cgGLSetParameter3f(r_cg_permutation->fp_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);CHECKCGERROR
6059 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);CHECKCGERROR
6060 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);CHECKCGERROR
6061 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);CHECKCGERROR
6062 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
6063 if (r_cg_permutation->fp_DeferredMod_Specular) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
6065 // additive passes are only darkened by fog, not tinted
6066 if (r_cg_permutation->fp_FogColor)
6068 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6069 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
6071 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6074 if (r_cg_permutation->fp_DistortScaleRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);CHECKCGERROR
6075 if (r_cg_permutation->fp_ScreenScaleRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);CHECKCGERROR
6076 if (r_cg_permutation->fp_ScreenCenterRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);CHECKCGERROR
6077 if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4f(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);CHECKCGERROR
6078 if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4f(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);CHECKCGERROR
6079 if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
6080 if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
6081 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6082 if (r_cg_permutation->fp_NormalmapScrollBlend) cgGLSetParameter2f(r_cg_permutation->fp_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
6084 if (r_cg_permutation->fp_ShadowMap_TextureScale) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);CHECKCGERROR
6085 if (r_cg_permutation->fp_ShadowMap_Parameters) cgGLSetParameter4f(r_cg_permutation->fp_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);CHECKCGERROR
6086 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
6087 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));CHECKCGERROR
6088 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6089 if (r_cg_permutation->fp_Color_Pants)
6091 if (rsurface.texture->pantstexture)
6092 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6094 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
6097 if (r_cg_permutation->fp_Color_Shirt)
6099 if (rsurface.texture->shirttexture)
6100 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6102 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
6105 if (r_cg_permutation->fp_FogPlane) cgGLSetParameter4f(r_cg_permutation->fp_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);CHECKCGERROR
6106 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
6107 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
6108 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
6109 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
6110 if (r_cg_permutation->fp_ScreenToDepth) cgGLSetParameter2f(r_cg_permutation->fp_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);CHECKCGERROR
6111 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6113 // if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_texture_white );CHECKCGERROR
6114 // if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_texture_white );CHECKCGERROR
6115 // if (r_cg_permutation->fp_Texture_GammaRamps ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps , r_texture_gammaramps );CHECKCGERROR
6116 if (r_cg_permutation->fp_Texture_Normal ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal , rsurface.texture->nmaptexture );CHECKCGERROR
6117 if (r_cg_permutation->fp_Texture_Color ) CG_BindTexture(r_cg_permutation->fp_Texture_Color , rsurface.texture->basetexture );CHECKCGERROR
6118 if (r_cg_permutation->fp_Texture_Gloss ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss , rsurface.texture->glosstexture );CHECKCGERROR
6119 if (r_cg_permutation->fp_Texture_Glow ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow , rsurface.texture->glowtexture );CHECKCGERROR
6120 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture );CHECKCGERROR
6121 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );CHECKCGERROR
6122 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );CHECKCGERROR
6123 if (r_cg_permutation->fp_Texture_SecondaryGlow ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );CHECKCGERROR
6124 if (r_cg_permutation->fp_Texture_Pants ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants , rsurface.texture->pantstexture );CHECKCGERROR
6125 if (r_cg_permutation->fp_Texture_Shirt ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt , rsurface.texture->shirttexture );CHECKCGERROR
6126 if (r_cg_permutation->fp_Texture_ReflectMask ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask , rsurface.texture->reflectmasktexture );CHECKCGERROR
6127 if (r_cg_permutation->fp_Texture_ReflectCube ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectCube , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);CHECKCGERROR
6128 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture );CHECKCGERROR
6129 if (r_cg_permutation->fp_Texture_FogMask ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask , r_texture_fogattenuation );CHECKCGERROR
6130 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
6131 if (r_cg_permutation->fp_Texture_Deluxemap ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
6132 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
6133 if (rsurfacepass == RSURFPASS_BACKGROUND)
6135 if (r_cg_permutation->fp_Texture_Refraction ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);CHECKCGERROR
6136 else if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);CHECKCGERROR
6137 if (r_cg_permutation->fp_Texture_Reflection ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);CHECKCGERROR
6141 if (r_cg_permutation->fp_Texture_Reflection ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);CHECKCGERROR
6143 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
6144 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
6145 if (r_cg_permutation->fp_Texture_ScreenDiffuse ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );CHECKCGERROR
6146 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );CHECKCGERROR
6147 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6149 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
6150 if (rsurface.rtlight)
6152 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
6153 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
6160 case RENDERPATH_GL13:
6161 case RENDERPATH_GL11:
6163 case RENDERPATH_SOFT:
6164 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
6165 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
6166 R_SetupShader_SetPermutationSoft(mode, permutation);
6167 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
6168 if (mode == SHADERMODE_LIGHTSOURCE)
6170 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
6171 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
6172 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
6173 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
6174 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
6175 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
6177 // additive passes are only darkened by fog, not tinted
6178 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
6179 DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6183 if (mode == SHADERMODE_FLATCOLOR)
6185 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
6187 else if (mode == SHADERMODE_LIGHTDIRECTION)
6189 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
6190 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
6191 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
6192 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
6193 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
6194 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
6195 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
6199 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
6200 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
6201 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
6202 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
6203 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
6205 // additive passes are only darkened by fog, not tinted
6206 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6207 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
6209 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6210 DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
6211 DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
6212 DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
6213 DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
6214 DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
6215 DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
6216 DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
6217 DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6218 DPSOFTRAST_Uniform2fARB(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
6220 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
6221 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
6222 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
6223 DPSOFTRAST_Uniform2fARB(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6224 DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6226 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
6227 DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
6228 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
6229 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
6231 if (rsurface.texture->pantstexture)
6232 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6234 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
6236 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
6238 if (rsurface.texture->shirttexture)
6239 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6241 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
6243 DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
6244 DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
6245 DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
6246 DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
6247 DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
6248 DPSOFTRAST_Uniform2fARB(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6249 DPSOFTRAST_Uniform2fARB(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6251 // R_Mesh_TexBind(GL20TU_FIRST , r_texture_white );
6252 // R_Mesh_TexBind(GL20TU_SECOND , r_texture_white );
6253 // R_Mesh_TexBind(GL20TU_GAMMARAMPS , r_texture_gammaramps );
6254 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
6255 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
6256 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
6257 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
6258 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
6259 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
6260 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
6261 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
6262 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
6263 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
6264 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
6265 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
6266 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
6267 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
6268 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
6269 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
6270 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
6271 if (rsurfacepass == RSURFPASS_BACKGROUND)
6273 if(DPSOFTRAST_UNIFORM_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
6274 else if(DPSOFTRAST_UNIFORM_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
6275 if(DPSOFTRAST_UNIFORM_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
6279 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
6281 // R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
6282 // R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
6283 R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
6284 R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
6285 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6287 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture );
6288 if (rsurface.rtlight)
6290 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
6291 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
6298 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6300 // select a permutation of the lighting shader appropriate to this
6301 // combination of texture, entity, light source, and fogging, only use the
6302 // minimum features necessary to avoid wasting rendering time in the
6303 // fragment shader on features that are not being used
6304 unsigned int permutation = 0;
6305 unsigned int mode = 0;
6306 const float *lightcolorbase = rtlight->currentcolor;
6307 float ambientscale = rtlight->ambientscale;
6308 float diffusescale = rtlight->diffusescale;
6309 float specularscale = rtlight->specularscale;
6310 // this is the location of the light in view space
6311 vec3_t viewlightorigin;
6312 // this transforms from view space (camera) to light space (cubemap)
6313 matrix4x4_t viewtolight;
6314 matrix4x4_t lighttoview;
6315 float viewtolight16f[16];
6316 float range = 1.0f / r_shadow_deferred_8bitrange.value;
6318 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6319 if (rtlight->currentcubemap != r_texture_whitecube)
6320 permutation |= SHADERPERMUTATION_CUBEFILTER;
6321 if (diffusescale > 0)
6322 permutation |= SHADERPERMUTATION_DIFFUSE;
6323 if (specularscale > 0)
6324 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6325 if (r_shadow_usingshadowmap2d)
6327 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6328 if (r_shadow_shadowmapvsdct)
6329 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6331 if (r_shadow_shadowmapsampler)
6332 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6333 if (r_shadow_shadowmappcf > 1)
6334 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6335 else if (r_shadow_shadowmappcf)
6336 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6338 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6339 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6340 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6341 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6342 switch(vid.renderpath)
6344 case RENDERPATH_D3D9:
6346 R_SetupShader_SetPermutationHLSL(mode, permutation);
6347 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6348 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6349 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
6350 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
6351 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6352 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6353 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6354 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6355 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6356 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6358 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
6359 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
6360 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
6361 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
6362 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
6363 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
6366 case RENDERPATH_D3D10:
6367 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6369 case RENDERPATH_D3D11:
6370 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6372 case RENDERPATH_GL20:
6373 R_SetupShader_SetPermutationGLSL(mode, permutation);
6374 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6375 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
6376 if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3fARB( r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
6377 if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3fARB( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
6378 if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3fARB( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6379 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2fARB( r_glsl_permutation->loc_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6380 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4fARB( r_glsl_permutation->loc_ShadowMap_Parameters , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6381 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB( r_glsl_permutation->loc_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6382 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2fARB( r_glsl_permutation->loc_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6383 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6385 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
6386 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
6387 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
6388 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
6389 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
6390 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
6392 case RENDERPATH_CGGL:
6394 R_SetupShader_SetPermutationCG(mode, permutation);
6395 if (r_cg_permutation->fp_LightPosition ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6396 if (r_cg_permutation->fp_ViewToLight ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6397 if (r_cg_permutation->fp_DeferredColor_Ambient ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);CHECKCGERROR
6398 if (r_cg_permutation->fp_DeferredColor_Diffuse ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);CHECKCGERROR
6399 if (r_cg_permutation->fp_DeferredColor_Specular ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);CHECKCGERROR
6400 if (r_cg_permutation->fp_ShadowMap_TextureScale ) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);CHECKCGERROR
6401 if (r_cg_permutation->fp_ShadowMap_Parameters ) cgGLSetParameter4f(r_cg_permutation->fp_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);CHECKCGERROR
6402 if (r_cg_permutation->fp_SpecularPower ) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6403 if (r_cg_permutation->fp_ScreenToDepth ) cgGLSetParameter2f(r_cg_permutation->fp_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);CHECKCGERROR
6404 if (r_cg_permutation->fp_PixelToScreenTexCoord ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6406 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
6407 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
6408 if (r_cg_permutation->fp_Texture_ScreenNormalMap ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
6409 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
6410 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
6411 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
6414 case RENDERPATH_GL13:
6415 case RENDERPATH_GL11:
6417 case RENDERPATH_SOFT:
6418 R_SetupShader_SetPermutationGLSL(mode, permutation);
6419 DPSOFTRAST_Uniform3fARB( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6420 DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
6421 DPSOFTRAST_Uniform3fARB( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
6422 DPSOFTRAST_Uniform3fARB( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
6423 DPSOFTRAST_Uniform3fARB( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6424 DPSOFTRAST_Uniform2fARB( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6425 DPSOFTRAST_Uniform4fARB( DPSOFTRAST_UNIFORM_ShadowMap_Parameters , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6426 DPSOFTRAST_Uniform1fARB( DPSOFTRAST_UNIFORM_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6427 DPSOFTRAST_Uniform2fARB( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6428 DPSOFTRAST_Uniform2fARB(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6430 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
6431 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
6432 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
6433 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
6434 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
6435 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
6440 #define SKINFRAME_HASH 1024
6444 int loadsequence; // incremented each level change
6445 memexpandablearray_t array;
6446 skinframe_t *hash[SKINFRAME_HASH];
6449 r_skinframe_t r_skinframe;
6451 void R_SkinFrame_PrepareForPurge(void)
6453 r_skinframe.loadsequence++;
6454 // wrap it without hitting zero
6455 if (r_skinframe.loadsequence >= 200)
6456 r_skinframe.loadsequence = 1;
6459 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6463 // mark the skinframe as used for the purging code
6464 skinframe->loadsequence = r_skinframe.loadsequence;
6467 void R_SkinFrame_Purge(void)
6471 for (i = 0;i < SKINFRAME_HASH;i++)
6473 for (s = r_skinframe.hash[i];s;s = s->next)
6475 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6477 if (s->merged == s->base)
6479 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6480 R_PurgeTexture(s->stain );s->stain = NULL;
6481 R_PurgeTexture(s->merged);s->merged = NULL;
6482 R_PurgeTexture(s->base );s->base = NULL;
6483 R_PurgeTexture(s->pants );s->pants = NULL;
6484 R_PurgeTexture(s->shirt );s->shirt = NULL;
6485 R_PurgeTexture(s->nmap );s->nmap = NULL;
6486 R_PurgeTexture(s->gloss );s->gloss = NULL;
6487 R_PurgeTexture(s->glow );s->glow = NULL;
6488 R_PurgeTexture(s->fog );s->fog = NULL;
6489 R_PurgeTexture(s->reflect);s->reflect = NULL;
6490 s->loadsequence = 0;
6496 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6498 char basename[MAX_QPATH];
6500 Image_StripImageExtension(name, basename, sizeof(basename));
6502 if( last == NULL ) {
6504 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6505 item = r_skinframe.hash[hashindex];
6510 // linearly search through the hash bucket
6511 for( ; item ; item = item->next ) {
6512 if( !strcmp( item->basename, basename ) ) {
6519 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6523 char basename[MAX_QPATH];
6525 Image_StripImageExtension(name, basename, sizeof(basename));
6527 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6528 for (item = r_skinframe.hash[hashindex];item;item = item->next)
6529 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6533 rtexture_t *dyntexture;
6534 // check whether its a dynamic texture
6535 dyntexture = CL_GetDynTexture( basename );
6536 if (!add && !dyntexture)
6538 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6539 memset(item, 0, sizeof(*item));
6540 strlcpy(item->basename, basename, sizeof(item->basename));
6541 item->base = dyntexture; // either NULL or dyntexture handle
6542 item->textureflags = textureflags;
6543 item->comparewidth = comparewidth;
6544 item->compareheight = compareheight;
6545 item->comparecrc = comparecrc;
6546 item->next = r_skinframe.hash[hashindex];
6547 r_skinframe.hash[hashindex] = item;
6549 else if( item->base == NULL )
6551 rtexture_t *dyntexture;
6552 // check whether its a dynamic texture
6553 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
6554 dyntexture = CL_GetDynTexture( basename );
6555 item->base = dyntexture; // either NULL or dyntexture handle
6558 R_SkinFrame_MarkUsed(item);
6562 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6564 unsigned long long avgcolor[5], wsum; \
6572 for(pix = 0; pix < cnt; ++pix) \
6575 for(comp = 0; comp < 3; ++comp) \
6577 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6580 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6582 for(comp = 0; comp < 3; ++comp) \
6583 avgcolor[comp] += getpixel * w; \
6586 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6587 avgcolor[4] += getpixel; \
6589 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6591 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6592 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6593 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6594 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6597 extern cvar_t gl_picmip;
6598 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6601 unsigned char *pixels;
6602 unsigned char *bumppixels;
6603 unsigned char *basepixels = NULL;
6604 int basepixels_width = 0;
6605 int basepixels_height = 0;
6606 skinframe_t *skinframe;
6607 rtexture_t *ddsbase = NULL;
6608 qboolean ddshasalpha = false;
6609 float ddsavgcolor[4];
6610 char basename[MAX_QPATH];
6611 int miplevel = R_PicmipForFlags(textureflags);
6612 int savemiplevel = miplevel;
6615 if (cls.state == ca_dedicated)
6618 // return an existing skinframe if already loaded
6619 // if loading of the first image fails, don't make a new skinframe as it
6620 // would cause all future lookups of this to be missing
6621 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6622 if (skinframe && skinframe->base)
6625 Image_StripImageExtension(name, basename, sizeof(basename));
6627 // check for DDS texture file first
6628 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6630 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6631 if (basepixels == NULL)
6635 // FIXME handle miplevel
6637 if (developer_loading.integer)
6638 Con_Printf("loading skin \"%s\"\n", name);
6640 // we've got some pixels to store, so really allocate this new texture now
6642 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6643 skinframe->stain = NULL;
6644 skinframe->merged = NULL;
6645 skinframe->base = NULL;
6646 skinframe->pants = NULL;
6647 skinframe->shirt = NULL;
6648 skinframe->nmap = NULL;
6649 skinframe->gloss = NULL;
6650 skinframe->glow = NULL;
6651 skinframe->fog = NULL;
6652 skinframe->reflect = NULL;
6653 skinframe->hasalpha = false;
6657 skinframe->base = ddsbase;
6658 skinframe->hasalpha = ddshasalpha;
6659 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6660 if (r_loadfog && skinframe->hasalpha)
6661 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6662 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
6666 basepixels_width = image_width;
6667 basepixels_height = image_height;
6668 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
6669 if (textureflags & TEXF_ALPHA)
6671 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6673 if (basepixels[j] < 255)
6675 skinframe->hasalpha = true;
6679 if (r_loadfog && skinframe->hasalpha)
6681 // has transparent pixels
6682 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6683 for (j = 0;j < image_width * image_height * 4;j += 4)
6688 pixels[j+3] = basepixels[j+3];
6690 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
6694 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6695 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
6696 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6697 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6698 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6699 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6704 mymiplevel = savemiplevel;
6705 if (r_loadnormalmap)
6706 skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
6707 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6709 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6710 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6711 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6712 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6715 // _norm is the name used by tenebrae and has been adopted as standard
6716 if (r_loadnormalmap && skinframe->nmap == NULL)
6718 mymiplevel = savemiplevel;
6719 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6721 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6725 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6727 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6728 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6729 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6731 Mem_Free(bumppixels);
6733 else if (r_shadow_bumpscale_basetexture.value > 0)
6735 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6736 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6737 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6740 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6741 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6744 // _luma is supported only for tenebrae compatibility
6745 // _glow is the preferred name
6746 mymiplevel = savemiplevel;
6747 if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel))))
6749 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6750 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6751 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6752 Mem_Free(pixels);pixels = NULL;
6755 mymiplevel = savemiplevel;
6756 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6758 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6759 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6760 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6765 mymiplevel = savemiplevel;
6766 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6768 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6769 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6770 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6775 mymiplevel = savemiplevel;
6776 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6778 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6779 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6780 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6785 mymiplevel = savemiplevel;
6786 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6788 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6789 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6790 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6796 Mem_Free(basepixels);
6801 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6802 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6805 unsigned char *temp1, *temp2;
6806 skinframe_t *skinframe;
6808 if (cls.state == ca_dedicated)
6811 // if already loaded just return it, otherwise make a new skinframe
6812 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6813 if (skinframe && skinframe->base)
6816 skinframe->stain = NULL;
6817 skinframe->merged = NULL;
6818 skinframe->base = NULL;
6819 skinframe->pants = NULL;
6820 skinframe->shirt = NULL;
6821 skinframe->nmap = NULL;
6822 skinframe->gloss = NULL;
6823 skinframe->glow = NULL;
6824 skinframe->fog = NULL;
6825 skinframe->reflect = NULL;
6826 skinframe->hasalpha = false;
6828 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6832 if (developer_loading.integer)
6833 Con_Printf("loading 32bit skin \"%s\"\n", name);
6835 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6837 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6838 temp2 = temp1 + width * height * 4;
6839 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6840 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
6843 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6844 if (textureflags & TEXF_ALPHA)
6846 for (i = 3;i < width * height * 4;i += 4)
6848 if (skindata[i] < 255)
6850 skinframe->hasalpha = true;
6854 if (r_loadfog && skinframe->hasalpha)
6856 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6857 memcpy(fogpixels, skindata, width * height * 4);
6858 for (i = 0;i < width * height * 4;i += 4)
6859 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6860 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6861 Mem_Free(fogpixels);
6865 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6866 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
6871 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6875 skinframe_t *skinframe;
6877 if (cls.state == ca_dedicated)
6880 // if already loaded just return it, otherwise make a new skinframe
6881 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6882 if (skinframe && skinframe->base)
6885 skinframe->stain = NULL;
6886 skinframe->merged = NULL;
6887 skinframe->base = NULL;
6888 skinframe->pants = NULL;
6889 skinframe->shirt = NULL;
6890 skinframe->nmap = NULL;
6891 skinframe->gloss = NULL;
6892 skinframe->glow = NULL;
6893 skinframe->fog = NULL;
6894 skinframe->reflect = NULL;
6895 skinframe->hasalpha = false;
6897 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6901 if (developer_loading.integer)
6902 Con_Printf("loading quake skin \"%s\"\n", name);
6904 // we actually don't upload anything until the first use, because mdl skins frequently go unused, and are almost never used in both modes (colormapped and non-colormapped)
6905 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
6906 memcpy(skinframe->qpixels, skindata, width*height);
6907 skinframe->qwidth = width;
6908 skinframe->qheight = height;
6911 for (i = 0;i < width * height;i++)
6912 featuresmask |= palette_featureflags[skindata[i]];
6914 skinframe->hasalpha = false;
6915 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6916 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6917 skinframe->qgeneratemerged = true;
6918 skinframe->qgeneratebase = skinframe->qhascolormapping;
6919 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6921 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6922 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
6927 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6931 unsigned char *skindata;
6933 if (!skinframe->qpixels)
6936 if (!skinframe->qhascolormapping)
6937 colormapped = false;
6941 if (!skinframe->qgeneratebase)
6946 if (!skinframe->qgeneratemerged)
6950 width = skinframe->qwidth;
6951 height = skinframe->qheight;
6952 skindata = skinframe->qpixels;
6954 if (skinframe->qgeneratenmap)
6956 unsigned char *temp1, *temp2;
6957 skinframe->qgeneratenmap = false;
6958 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6959 temp2 = temp1 + width * height * 4;
6960 // use either a custom palette or the quake palette
6961 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6962 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6963 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
6967 if (skinframe->qgenerateglow)
6969 skinframe->qgenerateglow = false;
6970 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6975 skinframe->qgeneratebase = false;
6976 skinframe->base = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
6977 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6978 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6982 skinframe->qgeneratemerged = false;
6983 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
6986 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6988 Mem_Free(skinframe->qpixels);
6989 skinframe->qpixels = NULL;
6993 skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette)
6996 skinframe_t *skinframe;
6998 if (cls.state == ca_dedicated)
7001 // if already loaded just return it, otherwise make a new skinframe
7002 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
7003 if (skinframe && skinframe->base)
7006 skinframe->stain = NULL;
7007 skinframe->merged = NULL;
7008 skinframe->base = NULL;
7009 skinframe->pants = NULL;
7010 skinframe->shirt = NULL;
7011 skinframe->nmap = NULL;
7012 skinframe->gloss = NULL;
7013 skinframe->glow = NULL;
7014 skinframe->fog = NULL;
7015 skinframe->reflect = NULL;
7016 skinframe->hasalpha = false;
7018 // if no data was provided, then clearly the caller wanted to get a blank skinframe
7022 if (developer_loading.integer)
7023 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
7025 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
7026 if (textureflags & TEXF_ALPHA)
7028 for (i = 0;i < width * height;i++)
7030 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
7032 skinframe->hasalpha = true;
7036 if (r_loadfog && skinframe->hasalpha)
7037 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
7040 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
7041 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
7046 skinframe_t *R_SkinFrame_LoadMissing(void)
7048 skinframe_t *skinframe;
7050 if (cls.state == ca_dedicated)
7053 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
7054 skinframe->stain = NULL;
7055 skinframe->merged = NULL;
7056 skinframe->base = NULL;
7057 skinframe->pants = NULL;
7058 skinframe->shirt = NULL;
7059 skinframe->nmap = NULL;
7060 skinframe->gloss = NULL;
7061 skinframe->glow = NULL;
7062 skinframe->fog = NULL;
7063 skinframe->reflect = NULL;
7064 skinframe->hasalpha = false;
7066 skinframe->avgcolor[0] = rand() / RAND_MAX;
7067 skinframe->avgcolor[1] = rand() / RAND_MAX;
7068 skinframe->avgcolor[2] = rand() / RAND_MAX;
7069 skinframe->avgcolor[3] = 1;
7074 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
7075 typedef struct suffixinfo_s
7078 qboolean flipx, flipy, flipdiagonal;
7081 static suffixinfo_t suffix[3][6] =
7084 {"px", false, false, false},
7085 {"nx", false, false, false},
7086 {"py", false, false, false},
7087 {"ny", false, false, false},
7088 {"pz", false, false, false},
7089 {"nz", false, false, false}
7092 {"posx", false, false, false},
7093 {"negx", false, false, false},
7094 {"posy", false, false, false},
7095 {"negy", false, false, false},
7096 {"posz", false, false, false},
7097 {"negz", false, false, false}
7100 {"rt", true, false, true},
7101 {"lf", false, true, true},
7102 {"ft", true, true, false},
7103 {"bk", false, false, false},
7104 {"up", true, false, true},
7105 {"dn", true, false, true}
7109 static int componentorder[4] = {0, 1, 2, 3};
7111 rtexture_t *R_LoadCubemap(const char *basename)
7113 int i, j, cubemapsize;
7114 unsigned char *cubemappixels, *image_buffer;
7115 rtexture_t *cubemaptexture;
7117 // must start 0 so the first loadimagepixels has no requested width/height
7119 cubemappixels = NULL;
7120 cubemaptexture = NULL;
7121 // keep trying different suffix groups (posx, px, rt) until one loads
7122 for (j = 0;j < 3 && !cubemappixels;j++)
7124 // load the 6 images in the suffix group
7125 for (i = 0;i < 6;i++)
7127 // generate an image name based on the base and and suffix
7128 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
7130 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
7132 // an image loaded, make sure width and height are equal
7133 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
7135 // if this is the first image to load successfully, allocate the cubemap memory
7136 if (!cubemappixels && image_width >= 1)
7138 cubemapsize = image_width;
7139 // note this clears to black, so unavailable sides are black
7140 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
7142 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
7144 Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_buffer, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder);
7147 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
7149 Mem_Free(image_buffer);
7153 // if a cubemap loaded, upload it
7156 if (developer_loading.integer)
7157 Con_Printf("loading cubemap \"%s\"\n", basename);
7159 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
7160 Mem_Free(cubemappixels);
7164 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
7165 if (developer_loading.integer)
7167 Con_Printf("(tried tried images ");
7168 for (j = 0;j < 3;j++)
7169 for (i = 0;i < 6;i++)
7170 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
7171 Con_Print(" and was unable to find any of them).\n");
7174 return cubemaptexture;
7177 rtexture_t *R_GetCubemap(const char *basename)
7180 for (i = 0;i < r_texture_numcubemaps;i++)
7181 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
7182 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
7183 if (i >= MAX_CUBEMAPS)
7184 return r_texture_whitecube;
7185 r_texture_numcubemaps++;
7186 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
7187 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
7188 return r_texture_cubemaps[i].texture;
7191 void R_FreeCubemaps(void)
7194 for (i = 0;i < r_texture_numcubemaps;i++)
7196 if (developer_loading.integer)
7197 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
7198 if (r_texture_cubemaps[i].texture)
7199 R_FreeTexture(r_texture_cubemaps[i].texture);
7201 r_texture_numcubemaps = 0;
7204 void R_Main_FreeViewCache(void)
7206 if (r_refdef.viewcache.entityvisible)
7207 Mem_Free(r_refdef.viewcache.entityvisible);
7208 if (r_refdef.viewcache.world_pvsbits)
7209 Mem_Free(r_refdef.viewcache.world_pvsbits);
7210 if (r_refdef.viewcache.world_leafvisible)
7211 Mem_Free(r_refdef.viewcache.world_leafvisible);
7212 if (r_refdef.viewcache.world_surfacevisible)
7213 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7214 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
7217 void R_Main_ResizeViewCache(void)
7219 int numentities = r_refdef.scene.numentities;
7220 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
7221 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
7222 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
7223 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
7224 if (r_refdef.viewcache.maxentities < numentities)
7226 r_refdef.viewcache.maxentities = numentities;
7227 if (r_refdef.viewcache.entityvisible)
7228 Mem_Free(r_refdef.viewcache.entityvisible);
7229 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
7231 if (r_refdef.viewcache.world_numclusters != numclusters)
7233 r_refdef.viewcache.world_numclusters = numclusters;
7234 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
7235 if (r_refdef.viewcache.world_pvsbits)
7236 Mem_Free(r_refdef.viewcache.world_pvsbits);
7237 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
7239 if (r_refdef.viewcache.world_numleafs != numleafs)
7241 r_refdef.viewcache.world_numleafs = numleafs;
7242 if (r_refdef.viewcache.world_leafvisible)
7243 Mem_Free(r_refdef.viewcache.world_leafvisible);
7244 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
7246 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
7248 r_refdef.viewcache.world_numsurfaces = numsurfaces;
7249 if (r_refdef.viewcache.world_surfacevisible)
7250 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7251 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
7255 extern rtexture_t *loadingscreentexture;
7256 void gl_main_start(void)
7258 loadingscreentexture = NULL;
7259 r_texture_blanknormalmap = NULL;
7260 r_texture_white = NULL;
7261 r_texture_grey128 = NULL;
7262 r_texture_black = NULL;
7263 r_texture_whitecube = NULL;
7264 r_texture_normalizationcube = NULL;
7265 r_texture_fogattenuation = NULL;
7266 r_texture_fogheighttexture = NULL;
7267 r_texture_gammaramps = NULL;
7268 r_texture_numcubemaps = 0;
7270 r_loaddds = r_texture_dds_load.integer != 0;
7271 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
7273 switch(vid.renderpath)
7275 case RENDERPATH_GL20:
7276 case RENDERPATH_CGGL:
7277 case RENDERPATH_D3D9:
7278 case RENDERPATH_D3D10:
7279 case RENDERPATH_D3D11:
7280 case RENDERPATH_SOFT:
7281 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7282 Cvar_SetValueQuick(&gl_combine, 1);
7283 Cvar_SetValueQuick(&r_glsl, 1);
7284 r_loadnormalmap = true;
7288 case RENDERPATH_GL13:
7289 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7290 Cvar_SetValueQuick(&gl_combine, 1);
7291 Cvar_SetValueQuick(&r_glsl, 0);
7292 r_loadnormalmap = false;
7293 r_loadgloss = false;
7296 case RENDERPATH_GL11:
7297 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7298 Cvar_SetValueQuick(&gl_combine, 0);
7299 Cvar_SetValueQuick(&r_glsl, 0);
7300 r_loadnormalmap = false;
7301 r_loadgloss = false;
7307 R_FrameData_Reset();
7311 memset(r_queries, 0, sizeof(r_queries));
7313 r_qwskincache = NULL;
7314 r_qwskincache_size = 0;
7316 // set up r_skinframe loading system for textures
7317 memset(&r_skinframe, 0, sizeof(r_skinframe));
7318 r_skinframe.loadsequence = 1;
7319 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7321 r_main_texturepool = R_AllocTexturePool();
7322 R_BuildBlankTextures();
7324 if (vid.support.arb_texture_cube_map)
7327 R_BuildNormalizationCube();
7329 r_texture_fogattenuation = NULL;
7330 r_texture_fogheighttexture = NULL;
7331 r_texture_gammaramps = NULL;
7332 //r_texture_fogintensity = NULL;
7333 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7334 memset(&r_waterstate, 0, sizeof(r_waterstate));
7335 r_glsl_permutation = NULL;
7336 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7337 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7338 glslshaderstring = NULL;
7340 r_cg_permutation = NULL;
7341 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7342 Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7343 cgshaderstring = NULL;
7346 r_hlsl_permutation = NULL;
7347 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7348 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7349 hlslshaderstring = NULL;
7351 memset(&r_svbsp, 0, sizeof (r_svbsp));
7353 r_refdef.fogmasktable_density = 0;
7356 void gl_main_shutdown(void)
7359 R_FrameData_Reset();
7361 R_Main_FreeViewCache();
7363 switch(vid.renderpath)
7365 case RENDERPATH_GL11:
7366 case RENDERPATH_GL13:
7367 case RENDERPATH_GL20:
7368 case RENDERPATH_CGGL:
7370 qglDeleteQueriesARB(r_maxqueries, r_queries);
7372 case RENDERPATH_D3D9:
7373 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7375 case RENDERPATH_D3D10:
7376 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7378 case RENDERPATH_D3D11:
7379 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7381 case RENDERPATH_SOFT:
7387 memset(r_queries, 0, sizeof(r_queries));
7389 r_qwskincache = NULL;
7390 r_qwskincache_size = 0;
7392 // clear out the r_skinframe state
7393 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7394 memset(&r_skinframe, 0, sizeof(r_skinframe));
7397 Mem_Free(r_svbsp.nodes);
7398 memset(&r_svbsp, 0, sizeof (r_svbsp));
7399 R_FreeTexturePool(&r_main_texturepool);
7400 loadingscreentexture = NULL;
7401 r_texture_blanknormalmap = NULL;
7402 r_texture_white = NULL;
7403 r_texture_grey128 = NULL;
7404 r_texture_black = NULL;
7405 r_texture_whitecube = NULL;
7406 r_texture_normalizationcube = NULL;
7407 r_texture_fogattenuation = NULL;
7408 r_texture_fogheighttexture = NULL;
7409 r_texture_gammaramps = NULL;
7410 r_texture_numcubemaps = 0;
7411 //r_texture_fogintensity = NULL;
7412 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7413 memset(&r_waterstate, 0, sizeof(r_waterstate));
7416 r_glsl_permutation = NULL;
7417 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7418 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
7419 glslshaderstring = NULL;
7421 r_cg_permutation = NULL;
7422 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7423 Mem_ExpandableArray_FreeArray(&r_cg_permutationarray);
7424 cgshaderstring = NULL;
7427 r_hlsl_permutation = NULL;
7428 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7429 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
7430 hlslshaderstring = NULL;
7434 extern void CL_ParseEntityLump(char *entitystring);
7435 void gl_main_newmap(void)
7437 // FIXME: move this code to client
7438 char *entities, entname[MAX_QPATH];
7440 Mem_Free(r_qwskincache);
7441 r_qwskincache = NULL;
7442 r_qwskincache_size = 0;
7445 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7446 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7448 CL_ParseEntityLump(entities);
7452 if (cl.worldmodel->brush.entities)
7453 CL_ParseEntityLump(cl.worldmodel->brush.entities);
7455 R_Main_FreeViewCache();
7457 R_FrameData_Reset();
7460 void GL_Main_Init(void)
7462 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7464 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7465 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7466 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7467 if (gamemode == GAME_NEHAHRA)
7469 Cvar_RegisterVariable (&gl_fogenable);
7470 Cvar_RegisterVariable (&gl_fogdensity);
7471 Cvar_RegisterVariable (&gl_fogred);
7472 Cvar_RegisterVariable (&gl_foggreen);
7473 Cvar_RegisterVariable (&gl_fogblue);
7474 Cvar_RegisterVariable (&gl_fogstart);
7475 Cvar_RegisterVariable (&gl_fogend);
7476 Cvar_RegisterVariable (&gl_skyclip);
7478 Cvar_RegisterVariable(&r_motionblur);
7479 Cvar_RegisterVariable(&r_motionblur_maxblur);
7480 Cvar_RegisterVariable(&r_motionblur_bmin);
7481 Cvar_RegisterVariable(&r_motionblur_vmin);
7482 Cvar_RegisterVariable(&r_motionblur_vmax);
7483 Cvar_RegisterVariable(&r_motionblur_vcoeff);
7484 Cvar_RegisterVariable(&r_motionblur_randomize);
7485 Cvar_RegisterVariable(&r_damageblur);
7486 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7487 Cvar_RegisterVariable(&r_equalize_entities_minambient);
7488 Cvar_RegisterVariable(&r_equalize_entities_by);
7489 Cvar_RegisterVariable(&r_equalize_entities_to);
7490 Cvar_RegisterVariable(&r_depthfirst);
7491 Cvar_RegisterVariable(&r_useinfinitefarclip);
7492 Cvar_RegisterVariable(&r_farclip_base);
7493 Cvar_RegisterVariable(&r_farclip_world);
7494 Cvar_RegisterVariable(&r_nearclip);
7495 Cvar_RegisterVariable(&r_showbboxes);
7496 Cvar_RegisterVariable(&r_showsurfaces);
7497 Cvar_RegisterVariable(&r_showtris);
7498 Cvar_RegisterVariable(&r_shownormals);
7499 Cvar_RegisterVariable(&r_showlighting);
7500 Cvar_RegisterVariable(&r_showshadowvolumes);
7501 Cvar_RegisterVariable(&r_showcollisionbrushes);
7502 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7503 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7504 Cvar_RegisterVariable(&r_showdisabledepthtest);
7505 Cvar_RegisterVariable(&r_drawportals);
7506 Cvar_RegisterVariable(&r_drawentities);
7507 Cvar_RegisterVariable(&r_draw2d);
7508 Cvar_RegisterVariable(&r_drawworld);
7509 Cvar_RegisterVariable(&r_cullentities_trace);
7510 Cvar_RegisterVariable(&r_cullentities_trace_samples);
7511 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7512 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7513 Cvar_RegisterVariable(&r_cullentities_trace_delay);
7514 Cvar_RegisterVariable(&r_drawviewmodel);
7515 Cvar_RegisterVariable(&r_drawexteriormodel);
7516 Cvar_RegisterVariable(&r_speeds);
7517 Cvar_RegisterVariable(&r_fullbrights);
7518 Cvar_RegisterVariable(&r_wateralpha);
7519 Cvar_RegisterVariable(&r_dynamic);
7520 Cvar_RegisterVariable(&r_fakelight);
7521 Cvar_RegisterVariable(&r_fakelight_intensity);
7522 Cvar_RegisterVariable(&r_fullbright);
7523 Cvar_RegisterVariable(&r_shadows);
7524 Cvar_RegisterVariable(&r_shadows_darken);
7525 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7526 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7527 Cvar_RegisterVariable(&r_shadows_throwdistance);
7528 Cvar_RegisterVariable(&r_shadows_throwdirection);
7529 Cvar_RegisterVariable(&r_shadows_focus);
7530 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7531 Cvar_RegisterVariable(&r_q1bsp_skymasking);
7532 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7533 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7534 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7535 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7536 Cvar_RegisterVariable(&r_fog_exp2);
7537 Cvar_RegisterVariable(&r_drawfog);
7538 Cvar_RegisterVariable(&r_transparentdepthmasking);
7539 Cvar_RegisterVariable(&r_texture_dds_load);
7540 Cvar_RegisterVariable(&r_texture_dds_save);
7541 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7542 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7543 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7544 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7545 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7546 Cvar_RegisterVariable(&r_textureunits);
7547 Cvar_RegisterVariable(&gl_combine);
7548 Cvar_RegisterVariable(&r_glsl);
7549 Cvar_RegisterVariable(&r_glsl_deluxemapping);
7550 Cvar_RegisterVariable(&r_glsl_offsetmapping);
7551 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7552 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7553 Cvar_RegisterVariable(&r_glsl_postprocess);
7554 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7555 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7556 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7557 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7558 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
7559 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
7560 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
7561 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
7563 Cvar_RegisterVariable(&r_water);
7564 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7565 Cvar_RegisterVariable(&r_water_clippingplanebias);
7566 Cvar_RegisterVariable(&r_water_refractdistort);
7567 Cvar_RegisterVariable(&r_water_reflectdistort);
7568 Cvar_RegisterVariable(&r_water_scissormode);
7569 Cvar_RegisterVariable(&r_lerpsprites);
7570 Cvar_RegisterVariable(&r_lerpmodels);
7571 Cvar_RegisterVariable(&r_lerplightstyles);
7572 Cvar_RegisterVariable(&r_waterscroll);
7573 Cvar_RegisterVariable(&r_bloom);
7574 Cvar_RegisterVariable(&r_bloom_colorscale);
7575 Cvar_RegisterVariable(&r_bloom_brighten);
7576 Cvar_RegisterVariable(&r_bloom_blur);
7577 Cvar_RegisterVariable(&r_bloom_resolution);
7578 Cvar_RegisterVariable(&r_bloom_colorexponent);
7579 Cvar_RegisterVariable(&r_bloom_colorsubtract);
7580 Cvar_RegisterVariable(&r_hdr);
7581 Cvar_RegisterVariable(&r_hdr_scenebrightness);
7582 Cvar_RegisterVariable(&r_hdr_glowintensity);
7583 Cvar_RegisterVariable(&r_hdr_range);
7584 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7585 Cvar_RegisterVariable(&developer_texturelogging);
7586 Cvar_RegisterVariable(&gl_lightmaps);
7587 Cvar_RegisterVariable(&r_test);
7588 Cvar_RegisterVariable(&r_glsl_saturation);
7589 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
7590 Cvar_RegisterVariable(&r_framedatasize);
7591 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7592 Cvar_SetValue("r_fullbrights", 0);
7593 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7595 Cvar_RegisterVariable(&r_track_sprites);
7596 Cvar_RegisterVariable(&r_track_sprites_flags);
7597 Cvar_RegisterVariable(&r_track_sprites_scalew);
7598 Cvar_RegisterVariable(&r_track_sprites_scaleh);
7599 Cvar_RegisterVariable(&r_overheadsprites_perspective);
7600 Cvar_RegisterVariable(&r_overheadsprites_pushback);
7601 Cvar_RegisterVariable(&r_overheadsprites_scalex);
7602 Cvar_RegisterVariable(&r_overheadsprites_scaley);
7605 extern void R_Textures_Init(void);
7606 extern void GL_Draw_Init(void);
7607 extern void GL_Main_Init(void);
7608 extern void R_Shadow_Init(void);
7609 extern void R_Sky_Init(void);
7610 extern void GL_Surf_Init(void);
7611 extern void R_Particles_Init(void);
7612 extern void R_Explosion_Init(void);
7613 extern void gl_backend_init(void);
7614 extern void Sbar_Init(void);
7615 extern void R_LightningBeams_Init(void);
7616 extern void Mod_RenderInit(void);
7617 extern void Font_Init(void);
7619 void Render_Init(void)
7632 R_LightningBeams_Init();
7641 extern char *ENGINE_EXTENSIONS;
7644 gl_renderer = (const char *)qglGetString(GL_RENDERER);
7645 gl_vendor = (const char *)qglGetString(GL_VENDOR);
7646 gl_version = (const char *)qglGetString(GL_VERSION);
7647 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7651 if (!gl_platformextensions)
7652 gl_platformextensions = "";
7654 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7655 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7656 Con_Printf("GL_VERSION: %s\n", gl_version);
7657 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7658 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7660 VID_CheckExtensions();
7662 // LordHavoc: report supported extensions
7663 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7665 // clear to black (loading plaque will be seen over this)
7666 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7669 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7673 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7675 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7678 p = r_refdef.view.frustum + i;
7683 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7687 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7691 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7695 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7699 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7703 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7707 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7711 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7719 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7723 for (i = 0;i < numplanes;i++)
7730 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7734 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7738 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7742 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7746 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7750 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7754 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7758 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7766 //==================================================================================
7768 // LordHavoc: this stores temporary data used within the same frame
7770 typedef struct r_framedata_mem_s
7772 struct r_framedata_mem_s *purge; // older mem block to free on next frame
7773 size_t size; // how much usable space
7774 size_t current; // how much space in use
7775 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
7776 size_t wantedsize; // how much space was allocated
7777 unsigned char *data; // start of real data (16byte aligned)
7781 static r_framedata_mem_t *r_framedata_mem;
7783 void R_FrameData_Reset(void)
7785 while (r_framedata_mem)
7787 r_framedata_mem_t *next = r_framedata_mem->purge;
7788 Mem_Free(r_framedata_mem);
7789 r_framedata_mem = next;
7793 void R_FrameData_Resize(void)
7796 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7797 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
7798 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
7800 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
7801 newmem->wantedsize = wantedsize;
7802 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
7803 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
7804 newmem->current = 0;
7806 newmem->purge = r_framedata_mem;
7807 r_framedata_mem = newmem;
7811 void R_FrameData_NewFrame(void)
7813 R_FrameData_Resize();
7814 if (!r_framedata_mem)
7816 // if we ran out of space on the last frame, free the old memory now
7817 while (r_framedata_mem->purge)
7819 // repeatedly remove the second item in the list, leaving only head
7820 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
7821 Mem_Free(r_framedata_mem->purge);
7822 r_framedata_mem->purge = next;
7824 // reset the current mem pointer
7825 r_framedata_mem->current = 0;
7826 r_framedata_mem->mark = 0;
7829 void *R_FrameData_Alloc(size_t size)
7833 // align to 16 byte boundary - the data pointer is already aligned, so we
7834 // only need to ensure the size of every allocation is also aligned
7835 size = (size + 15) & ~15;
7837 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
7839 // emergency - we ran out of space, allocate more memory
7840 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
7841 R_FrameData_Resize();
7844 data = r_framedata_mem->data + r_framedata_mem->current;
7845 r_framedata_mem->current += size;
7847 // count the usage for stats
7848 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
7849 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
7851 return (void *)data;
7854 void *R_FrameData_Store(size_t size, void *data)
7856 void *d = R_FrameData_Alloc(size);
7858 memcpy(d, data, size);
7862 void R_FrameData_SetMark(void)
7864 if (!r_framedata_mem)
7866 r_framedata_mem->mark = r_framedata_mem->current;
7869 void R_FrameData_ReturnToMark(void)
7871 if (!r_framedata_mem)
7873 r_framedata_mem->current = r_framedata_mem->mark;
7876 //==================================================================================
7878 // LordHavoc: animcache originally written by Echon, rewritten since then
7881 * Animation cache prevents re-generating mesh data for an animated model
7882 * multiple times in one frame for lighting, shadowing, reflections, etc.
7885 void R_AnimCache_Free(void)
7889 void R_AnimCache_ClearCache(void)
7892 entity_render_t *ent;
7894 for (i = 0;i < r_refdef.scene.numentities;i++)
7896 ent = r_refdef.scene.entities[i];
7897 ent->animcache_vertex3f = NULL;
7898 ent->animcache_normal3f = NULL;
7899 ent->animcache_svector3f = NULL;
7900 ent->animcache_tvector3f = NULL;
7901 ent->animcache_vertexmesh = NULL;
7902 ent->animcache_vertex3fbuffer = NULL;
7903 ent->animcache_vertexmeshbuffer = NULL;
7907 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7911 // check if we need the meshbuffers
7912 if (!vid.useinterleavedarrays)
7915 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7916 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7917 // TODO: upload vertex3f buffer?
7918 if (ent->animcache_vertexmesh)
7920 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7921 for (i = 0;i < numvertices;i++)
7922 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7923 if (ent->animcache_svector3f)
7924 for (i = 0;i < numvertices;i++)
7925 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7926 if (ent->animcache_tvector3f)
7927 for (i = 0;i < numvertices;i++)
7928 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7929 if (ent->animcache_normal3f)
7930 for (i = 0;i < numvertices;i++)
7931 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7932 // TODO: upload vertexmeshbuffer?
7936 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7938 dp_model_t *model = ent->model;
7940 // see if it's already cached this frame
7941 if (ent->animcache_vertex3f)
7943 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7944 if (wantnormals || wanttangents)
7946 if (ent->animcache_normal3f)
7947 wantnormals = false;
7948 if (ent->animcache_svector3f)
7949 wanttangents = false;
7950 if (wantnormals || wanttangents)
7952 numvertices = model->surfmesh.num_vertices;
7954 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7957 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7958 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7960 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7961 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7967 // see if this ent is worth caching
7968 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7970 // get some memory for this entity and generate mesh data
7971 numvertices = model->surfmesh.num_vertices;
7972 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7974 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7977 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7978 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7980 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7981 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7986 void R_AnimCache_CacheVisibleEntities(void)
7989 qboolean wantnormals = true;
7990 qboolean wanttangents = !r_showsurfaces.integer;
7992 switch(vid.renderpath)
7994 case RENDERPATH_GL20:
7995 case RENDERPATH_CGGL:
7996 case RENDERPATH_D3D9:
7997 case RENDERPATH_D3D10:
7998 case RENDERPATH_D3D11:
8000 case RENDERPATH_GL13:
8001 case RENDERPATH_GL11:
8002 wanttangents = false;
8004 case RENDERPATH_SOFT:
8008 if (r_shownormals.integer)
8009 wanttangents = wantnormals = true;
8011 // TODO: thread this
8012 // NOTE: R_PrepareRTLights() also caches entities
8014 for (i = 0;i < r_refdef.scene.numentities;i++)
8015 if (r_refdef.viewcache.entityvisible[i])
8016 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
8019 //==================================================================================
8021 static void R_View_UpdateEntityLighting (void)
8024 entity_render_t *ent;
8025 vec3_t tempdiffusenormal, avg;
8026 vec_t f, fa, fd, fdd;
8027 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
8029 for (i = 0;i < r_refdef.scene.numentities;i++)
8031 ent = r_refdef.scene.entities[i];
8033 // skip unseen models
8034 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
8038 if (ent->model && ent->model->brush.num_leafs)
8040 // TODO: use modellight for r_ambient settings on world?
8041 VectorSet(ent->modellight_ambient, 0, 0, 0);
8042 VectorSet(ent->modellight_diffuse, 0, 0, 0);
8043 VectorSet(ent->modellight_lightdir, 0, 0, 1);
8047 // fetch the lighting from the worldmodel data
8048 VectorClear(ent->modellight_ambient);
8049 VectorClear(ent->modellight_diffuse);
8050 VectorClear(tempdiffusenormal);
8051 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
8054 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8056 // complete lightning for lit sprites
8057 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
8058 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
8060 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
8061 org[2] = org[2] + r_overheadsprites_pushback.value;
8062 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, ent->modellight_lightdir, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
8065 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
8067 if(ent->flags & RENDER_EQUALIZE)
8069 // first fix up ambient lighting...
8070 if(r_equalize_entities_minambient.value > 0)
8072 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
8075 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
8076 if(fa < r_equalize_entities_minambient.value * fd)
8079 // fa'/fd' = minambient
8080 // fa'+0.25*fd' = fa+0.25*fd
8082 // fa' = fd' * minambient
8083 // fd'*(0.25+minambient) = fa+0.25*fd
8085 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
8086 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
8088 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
8089 f = fdd / fd; // f>0 because all this is additive; f<1 because fdd<fd because this follows from fa < r_equalize_entities_minambient.value * fd
8090 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
8091 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
8096 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
8098 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
8099 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
8103 // adjust brightness and saturation to target
8104 avg[0] = avg[1] = avg[2] = fa / f;
8105 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
8106 avg[0] = avg[1] = avg[2] = fd / f;
8107 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
8113 VectorSet(ent->modellight_ambient, 1, 1, 1);
8115 // move the light direction into modelspace coordinates for lighting code
8116 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
8117 if(VectorLength2(ent->modellight_lightdir) == 0)
8118 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
8119 VectorNormalize(ent->modellight_lightdir);
8123 #define MAX_LINEOFSIGHTTRACES 64
8125 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
8128 vec3_t boxmins, boxmaxs;
8131 dp_model_t *model = r_refdef.scene.worldmodel;
8133 if (!model || !model->brush.TraceLineOfSight)
8136 // expand the box a little
8137 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
8138 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
8139 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
8140 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
8141 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
8142 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
8144 // return true if eye is inside enlarged box
8145 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
8149 VectorCopy(eye, start);
8150 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
8151 if (model->brush.TraceLineOfSight(model, start, end))
8154 // try various random positions
8155 for (i = 0;i < numsamples;i++)
8157 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
8158 if (model->brush.TraceLineOfSight(model, start, end))
8166 static void R_View_UpdateEntityVisible (void)
8171 entity_render_t *ent;
8173 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8174 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8175 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
8176 : RENDER_EXTERIORMODEL;
8177 if (!r_drawviewmodel.integer)
8178 renderimask |= RENDER_VIEWMODEL;
8179 if (!r_drawexteriormodel.integer)
8180 renderimask |= RENDER_EXTERIORMODEL;
8181 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
8183 // worldmodel can check visibility
8184 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
8185 for (i = 0;i < r_refdef.scene.numentities;i++)
8187 ent = r_refdef.scene.entities[i];
8188 if (!(ent->flags & renderimask))
8189 if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
8190 if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
8191 r_refdef.viewcache.entityvisible[i] = true;
8193 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
8194 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
8196 for (i = 0;i < r_refdef.scene.numentities;i++)
8198 ent = r_refdef.scene.entities[i];
8199 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
8201 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
8203 continue; // temp entities do pvs only
8204 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
8205 ent->last_trace_visibility = realtime;
8206 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
8207 r_refdef.viewcache.entityvisible[i] = 0;
8214 // no worldmodel or it can't check visibility
8215 for (i = 0;i < r_refdef.scene.numentities;i++)
8217 ent = r_refdef.scene.entities[i];
8218 r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs));
8223 /// only used if skyrendermasked, and normally returns false
8224 int R_DrawBrushModelsSky (void)
8227 entity_render_t *ent;
8230 for (i = 0;i < r_refdef.scene.numentities;i++)
8232 if (!r_refdef.viewcache.entityvisible[i])
8234 ent = r_refdef.scene.entities[i];
8235 if (!ent->model || !ent->model->DrawSky)
8237 ent->model->DrawSky(ent);
8243 static void R_DrawNoModel(entity_render_t *ent);
8244 static void R_DrawModels(void)
8247 entity_render_t *ent;
8249 for (i = 0;i < r_refdef.scene.numentities;i++)
8251 if (!r_refdef.viewcache.entityvisible[i])
8253 ent = r_refdef.scene.entities[i];
8254 r_refdef.stats.entities++;
8255 if (ent->model && ent->model->Draw != NULL)
8256 ent->model->Draw(ent);
8262 static void R_DrawModelsDepth(void)
8265 entity_render_t *ent;
8267 for (i = 0;i < r_refdef.scene.numentities;i++)
8269 if (!r_refdef.viewcache.entityvisible[i])
8271 ent = r_refdef.scene.entities[i];
8272 if (ent->model && ent->model->DrawDepth != NULL)
8273 ent->model->DrawDepth(ent);
8277 static void R_DrawModelsDebug(void)
8280 entity_render_t *ent;
8282 for (i = 0;i < r_refdef.scene.numentities;i++)
8284 if (!r_refdef.viewcache.entityvisible[i])
8286 ent = r_refdef.scene.entities[i];
8287 if (ent->model && ent->model->DrawDebug != NULL)
8288 ent->model->DrawDebug(ent);
8292 static void R_DrawModelsAddWaterPlanes(void)
8295 entity_render_t *ent;
8297 for (i = 0;i < r_refdef.scene.numentities;i++)
8299 if (!r_refdef.viewcache.entityvisible[i])
8301 ent = r_refdef.scene.entities[i];
8302 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
8303 ent->model->DrawAddWaterPlanes(ent);
8307 static void R_View_SetFrustum(const int *scissor)
8310 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
8311 vec3_t forward, left, up, origin, v;
8315 // flipped x coordinates (because x points left here)
8316 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8317 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8319 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
8320 switch(vid.renderpath)
8322 case RENDERPATH_D3D9:
8323 case RENDERPATH_D3D10:
8324 case RENDERPATH_D3D11:
8325 case RENDERPATH_SOFT:
8326 // non-flipped y coordinates
8327 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8328 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8330 case RENDERPATH_GL11:
8331 case RENDERPATH_GL13:
8332 case RENDERPATH_GL20:
8333 case RENDERPATH_CGGL:
8334 // non-flipped y coordinates
8335 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8336 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8341 // we can't trust r_refdef.view.forward and friends in reflected scenes
8342 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
8345 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
8346 r_refdef.view.frustum[0].normal[1] = 0 - 0;
8347 r_refdef.view.frustum[0].normal[2] = -1 - 0;
8348 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
8349 r_refdef.view.frustum[1].normal[1] = 0 + 0;
8350 r_refdef.view.frustum[1].normal[2] = -1 + 0;
8351 r_refdef.view.frustum[2].normal[0] = 0 - 0;
8352 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
8353 r_refdef.view.frustum[2].normal[2] = -1 - 0;
8354 r_refdef.view.frustum[3].normal[0] = 0 + 0;
8355 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
8356 r_refdef.view.frustum[3].normal[2] = -1 + 0;
8360 zNear = r_refdef.nearclip;
8361 nudge = 1.0 - 1.0 / (1<<23);
8362 r_refdef.view.frustum[4].normal[0] = 0 - 0;
8363 r_refdef.view.frustum[4].normal[1] = 0 - 0;
8364 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
8365 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
8366 r_refdef.view.frustum[5].normal[0] = 0 + 0;
8367 r_refdef.view.frustum[5].normal[1] = 0 + 0;
8368 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
8369 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
8375 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8376 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8377 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8378 r_refdef.view.frustum[0].dist = m[15] - m[12];
8380 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8381 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8382 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8383 r_refdef.view.frustum[1].dist = m[15] + m[12];
8385 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8386 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8387 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8388 r_refdef.view.frustum[2].dist = m[15] - m[13];
8390 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8391 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8392 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8393 r_refdef.view.frustum[3].dist = m[15] + m[13];
8395 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8396 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8397 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8398 r_refdef.view.frustum[4].dist = m[15] - m[14];
8400 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8401 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8402 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8403 r_refdef.view.frustum[5].dist = m[15] + m[14];
8406 if (r_refdef.view.useperspective)
8408 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8409 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
8410 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]);
8411 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]);
8412 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
8414 // then the normals from the corners relative to origin
8415 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
8416 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
8417 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
8418 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
8420 // in a NORMAL view, forward cross left == up
8421 // in a REFLECTED view, forward cross left == down
8422 // so our cross products above need to be adjusted for a left handed coordinate system
8423 CrossProduct(forward, left, v);
8424 if(DotProduct(v, up) < 0)
8426 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
8427 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
8428 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
8429 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
8432 // Leaving those out was a mistake, those were in the old code, and they
8433 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8434 // I couldn't reproduce it after adding those normalizations. --blub
8435 VectorNormalize(r_refdef.view.frustum[0].normal);
8436 VectorNormalize(r_refdef.view.frustum[1].normal);
8437 VectorNormalize(r_refdef.view.frustum[2].normal);
8438 VectorNormalize(r_refdef.view.frustum[3].normal);
8440 // make the corners absolute
8441 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
8442 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
8443 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
8444 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
8447 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8449 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8450 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8451 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8452 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8453 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8457 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8458 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8459 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8460 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8461 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8462 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8463 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8464 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8465 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8466 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8468 r_refdef.view.numfrustumplanes = 5;
8470 if (r_refdef.view.useclipplane)
8472 r_refdef.view.numfrustumplanes = 6;
8473 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8476 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8477 PlaneClassify(r_refdef.view.frustum + i);
8479 // LordHavoc: note to all quake engine coders, Quake had a special case
8480 // for 90 degrees which assumed a square view (wrong), so I removed it,
8481 // Quake2 has it disabled as well.
8483 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8484 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8485 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8486 //PlaneClassify(&frustum[0]);
8488 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8489 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8490 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8491 //PlaneClassify(&frustum[1]);
8493 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8494 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8495 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8496 //PlaneClassify(&frustum[2]);
8498 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8499 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8500 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8501 //PlaneClassify(&frustum[3]);
8504 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8505 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8506 //PlaneClassify(&frustum[4]);
8509 void R_View_UpdateWithScissor(const int *myscissor)
8511 R_Main_ResizeViewCache();
8512 R_View_SetFrustum(myscissor);
8513 R_View_WorldVisibility(r_refdef.view.useclipplane);
8514 R_View_UpdateEntityVisible();
8515 R_View_UpdateEntityLighting();
8518 void R_View_Update(void)
8520 R_Main_ResizeViewCache();
8521 R_View_SetFrustum(NULL);
8522 R_View_WorldVisibility(r_refdef.view.useclipplane);
8523 R_View_UpdateEntityVisible();
8524 R_View_UpdateEntityLighting();
8527 void R_SetupView(qboolean allowwaterclippingplane)
8529 const float *customclipplane = NULL;
8531 if (r_refdef.view.useclipplane && allowwaterclippingplane)
8533 // LordHavoc: couldn't figure out how to make this approach the
8534 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8535 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8536 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8537 dist = r_refdef.view.clipplane.dist;
8538 plane[0] = r_refdef.view.clipplane.normal[0];
8539 plane[1] = r_refdef.view.clipplane.normal[1];
8540 plane[2] = r_refdef.view.clipplane.normal[2];
8542 customclipplane = plane;
8545 if (!r_refdef.view.useperspective)
8546 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
8547 else if (vid.stencil && r_useinfinitefarclip.integer)
8548 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
8550 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
8551 R_SetViewport(&r_refdef.view.viewport);
8554 void R_EntityMatrix(const matrix4x4_t *matrix)
8556 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8558 gl_modelmatrixchanged = false;
8559 gl_modelmatrix = *matrix;
8560 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8561 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8562 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8563 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8565 switch(vid.renderpath)
8567 case RENDERPATH_D3D9:
8569 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8570 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8573 case RENDERPATH_D3D10:
8574 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8576 case RENDERPATH_D3D11:
8577 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8579 case RENDERPATH_GL20:
8580 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8581 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8582 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8584 case RENDERPATH_CGGL:
8587 if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8588 if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8589 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8592 case RENDERPATH_GL13:
8593 case RENDERPATH_GL11:
8594 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8596 case RENDERPATH_SOFT:
8597 DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
8598 DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
8604 void R_ResetViewRendering2D(void)
8606 r_viewport_t viewport;
8609 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8610 R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, 1, 1, -10, 100, NULL);
8611 R_SetViewport(&viewport);
8612 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8613 GL_Color(1, 1, 1, 1);
8614 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8615 GL_BlendFunc(GL_ONE, GL_ZERO);
8616 GL_AlphaTest(false);
8617 GL_ScissorTest(false);
8618 GL_DepthMask(false);
8619 GL_DepthRange(0, 1);
8620 GL_DepthTest(false);
8621 GL_DepthFunc(GL_LEQUAL);
8622 R_EntityMatrix(&identitymatrix);
8623 R_Mesh_ResetTextureState();
8624 GL_PolygonOffset(0, 0);
8625 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8626 switch(vid.renderpath)
8628 case RENDERPATH_GL11:
8629 case RENDERPATH_GL13:
8630 case RENDERPATH_GL20:
8631 case RENDERPATH_CGGL:
8632 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8634 case RENDERPATH_D3D9:
8635 case RENDERPATH_D3D10:
8636 case RENDERPATH_D3D11:
8637 case RENDERPATH_SOFT:
8640 GL_CullFace(GL_NONE);
8643 void R_ResetViewRendering3D(void)
8648 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8649 GL_Color(1, 1, 1, 1);
8650 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8651 GL_BlendFunc(GL_ONE, GL_ZERO);
8652 GL_AlphaTest(false);
8653 GL_ScissorTest(true);
8655 GL_DepthRange(0, 1);
8657 GL_DepthFunc(GL_LEQUAL);
8658 R_EntityMatrix(&identitymatrix);
8659 R_Mesh_ResetTextureState();
8660 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8661 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8662 switch(vid.renderpath)
8664 case RENDERPATH_GL11:
8665 case RENDERPATH_GL13:
8666 case RENDERPATH_GL20:
8667 case RENDERPATH_CGGL:
8668 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8670 case RENDERPATH_D3D9:
8671 case RENDERPATH_D3D10:
8672 case RENDERPATH_D3D11:
8673 case RENDERPATH_SOFT:
8676 GL_CullFace(r_refdef.view.cullface_back);
8681 R_RenderView_UpdateViewVectors
8684 static void R_RenderView_UpdateViewVectors(void)
8686 // break apart the view matrix into vectors for various purposes
8687 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8688 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8689 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8690 VectorNegate(r_refdef.view.left, r_refdef.view.right);
8691 // make an inverted copy of the view matrix for tracking sprites
8692 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8695 void R_RenderScene(void);
8696 void R_RenderWaterPlanes(void);
8698 static void R_Water_StartFrame(void)
8701 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8702 r_waterstate_waterplane_t *p;
8704 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8707 switch(vid.renderpath)
8709 case RENDERPATH_GL20:
8710 case RENDERPATH_CGGL:
8711 case RENDERPATH_D3D9:
8712 case RENDERPATH_D3D10:
8713 case RENDERPATH_D3D11:
8714 case RENDERPATH_SOFT:
8716 case RENDERPATH_GL13:
8717 case RENDERPATH_GL11:
8721 // set waterwidth and waterheight to the water resolution that will be
8722 // used (often less than the screen resolution for faster rendering)
8723 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8724 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8726 // calculate desired texture sizes
8727 // can't use water if the card does not support the texture size
8728 if (!r_water.integer || r_showsurfaces.integer)
8729 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8730 else if (vid.support.arb_texture_non_power_of_two)
8732 texturewidth = waterwidth;
8733 textureheight = waterheight;
8734 camerawidth = waterwidth;
8735 cameraheight = waterheight;
8739 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
8740 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
8741 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
8742 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
8745 // allocate textures as needed
8746 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8748 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8749 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8751 if (p->texture_refraction)
8752 R_FreeTexture(p->texture_refraction);
8753 p->texture_refraction = NULL;
8754 if (p->texture_reflection)
8755 R_FreeTexture(p->texture_reflection);
8756 p->texture_reflection = NULL;
8757 if (p->texture_camera)
8758 R_FreeTexture(p->texture_camera);
8759 p->texture_camera = NULL;
8761 memset(&r_waterstate, 0, sizeof(r_waterstate));
8762 r_waterstate.texturewidth = texturewidth;
8763 r_waterstate.textureheight = textureheight;
8764 r_waterstate.camerawidth = camerawidth;
8765 r_waterstate.cameraheight = cameraheight;
8768 if (r_waterstate.texturewidth)
8770 r_waterstate.enabled = true;
8772 // when doing a reduced render (HDR) we want to use a smaller area
8773 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8774 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8776 // set up variables that will be used in shader setup
8777 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8778 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8779 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8780 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8783 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8784 r_waterstate.numwaterplanes = 0;
8787 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8789 int triangleindex, planeindex;
8795 r_waterstate_waterplane_t *p;
8796 texture_t *t = R_GetCurrentTexture(surface->texture);
8798 // just use the first triangle with a valid normal for any decisions
8799 VectorClear(normal);
8800 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8802 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8803 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8804 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8805 TriangleNormal(vert[0], vert[1], vert[2], normal);
8806 if (VectorLength2(normal) >= 0.001)
8810 VectorCopy(normal, plane.normal);
8811 VectorNormalize(plane.normal);
8812 plane.dist = DotProduct(vert[0], plane.normal);
8813 PlaneClassify(&plane);
8814 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8816 // skip backfaces (except if nocullface is set)
8817 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8819 VectorNegate(plane.normal, plane.normal);
8821 PlaneClassify(&plane);
8825 // find a matching plane if there is one
8826 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8827 if(p->camera_entity == t->camera_entity)
8828 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8830 if (planeindex >= r_waterstate.maxwaterplanes)
8831 return; // nothing we can do, out of planes
8833 // if this triangle does not fit any known plane rendered this frame, add one
8834 if (planeindex >= r_waterstate.numwaterplanes)
8836 // store the new plane
8837 r_waterstate.numwaterplanes++;
8839 // clear materialflags and pvs
8840 p->materialflags = 0;
8841 p->pvsvalid = false;
8842 p->camera_entity = t->camera_entity;
8843 VectorCopy(surface->mins, p->mins);
8844 VectorCopy(surface->maxs, p->maxs);
8849 p->mins[0] = min(p->mins[0], surface->mins[0]);
8850 p->mins[1] = min(p->mins[1], surface->mins[1]);
8851 p->mins[2] = min(p->mins[2], surface->mins[2]);
8852 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8853 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8854 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8856 // merge this surface's materialflags into the waterplane
8857 p->materialflags |= t->currentmaterialflags;
8858 if(!(p->materialflags & MATERIALFLAG_CAMERA))
8860 // merge this surface's PVS into the waterplane
8861 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8862 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8863 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8865 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8871 static void R_Water_ProcessPlanes(void)
8874 r_refdef_view_t originalview;
8875 r_refdef_view_t myview;
8877 r_waterstate_waterplane_t *p;
8880 originalview = r_refdef.view;
8882 // make sure enough textures are allocated
8883 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8885 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8887 if (!p->texture_refraction)
8888 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
8889 if (!p->texture_refraction)
8892 else if (p->materialflags & MATERIALFLAG_CAMERA)
8894 if (!p->texture_camera)
8895 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_waterstate.camerawidth, r_waterstate.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
8896 if (!p->texture_camera)
8900 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8902 if (!p->texture_reflection)
8903 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
8904 if (!p->texture_reflection)
8910 r_refdef.view = originalview;
8911 r_refdef.view.showdebug = false;
8912 r_refdef.view.width = r_waterstate.waterwidth;
8913 r_refdef.view.height = r_waterstate.waterheight;
8914 r_refdef.view.useclipplane = true;
8915 myview = r_refdef.view;
8916 r_waterstate.renderingscene = true;
8917 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8919 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8921 r_refdef.view = myview;
8922 if(r_water_scissormode.integer)
8925 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8926 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8929 // render reflected scene and copy into texture
8930 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8931 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8932 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8933 r_refdef.view.clipplane = p->plane;
8935 // reverse the cullface settings for this render
8936 r_refdef.view.cullface_front = GL_FRONT;
8937 r_refdef.view.cullface_back = GL_BACK;
8938 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8940 r_refdef.view.usecustompvs = true;
8942 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8944 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8947 R_ResetViewRendering3D();
8948 R_ClearScreen(r_refdef.fogenabled);
8949 if(r_water_scissormode.integer & 2)
8950 R_View_UpdateWithScissor(myscissor);
8953 if(r_water_scissormode.integer & 1)
8954 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8957 R_Mesh_CopyToTexture(p->texture_reflection, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8960 // render the normal view scene and copy into texture
8961 // (except that a clipping plane should be used to hide everything on one side of the water, and the viewer's weapon model should be omitted)
8962 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8964 r_refdef.view = myview;
8965 if(r_water_scissormode.integer)
8968 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8969 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8972 r_waterstate.renderingrefraction = true;
8974 r_refdef.view.clipplane = p->plane;
8975 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8976 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8978 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8980 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8981 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8982 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8983 R_RenderView_UpdateViewVectors();
8984 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8986 r_refdef.view.usecustompvs = true;
8987 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
8991 PlaneClassify(&r_refdef.view.clipplane);
8993 R_ResetViewRendering3D();
8994 R_ClearScreen(r_refdef.fogenabled);
8995 if(r_water_scissormode.integer & 2)
8996 R_View_UpdateWithScissor(myscissor);
8999 if(r_water_scissormode.integer & 1)
9000 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
9003 R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
9004 r_waterstate.renderingrefraction = false;
9006 else if (p->materialflags & MATERIALFLAG_CAMERA)
9008 r_refdef.view = myview;
9010 r_refdef.view.clipplane = p->plane;
9011 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
9012 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
9014 r_refdef.view.width = r_waterstate.camerawidth;
9015 r_refdef.view.height = r_waterstate.cameraheight;
9016 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
9017 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
9019 if(p->camera_entity)
9021 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
9022 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
9025 // note: all of the view is used for displaying... so
9026 // there is no use in scissoring
9028 // reverse the cullface settings for this render
9029 r_refdef.view.cullface_front = GL_FRONT;
9030 r_refdef.view.cullface_back = GL_BACK;
9031 // also reverse the view matrix
9032 Matrix4x4_ConcatScale3(&r_refdef.view.matrix, 1, 1, -1); // this serves to invert texcoords in the result, as the copied texture is mapped the wrong way round
9033 R_RenderView_UpdateViewVectors();
9034 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
9036 r_refdef.view.usecustompvs = true;
9037 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
9040 // camera needs no clipplane
9041 r_refdef.view.useclipplane = false;
9043 PlaneClassify(&r_refdef.view.clipplane);
9045 R_ResetViewRendering3D();
9046 R_ClearScreen(r_refdef.fogenabled);
9050 R_Mesh_CopyToTexture(p->texture_camera, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
9051 r_waterstate.renderingrefraction = false;
9055 r_waterstate.renderingscene = false;
9056 r_refdef.view = originalview;
9057 R_ResetViewRendering3D();
9058 R_ClearScreen(r_refdef.fogenabled);
9062 r_refdef.view = originalview;
9063 r_waterstate.renderingscene = false;
9064 Cvar_SetValueQuick(&r_water, 0);
9065 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
9069 void R_Bloom_StartFrame(void)
9071 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
9073 switch(vid.renderpath)
9075 case RENDERPATH_GL20:
9076 case RENDERPATH_CGGL:
9077 case RENDERPATH_D3D9:
9078 case RENDERPATH_D3D10:
9079 case RENDERPATH_D3D11:
9080 case RENDERPATH_SOFT:
9082 case RENDERPATH_GL13:
9083 case RENDERPATH_GL11:
9087 // set bloomwidth and bloomheight to the bloom resolution that will be
9088 // used (often less than the screen resolution for faster rendering)
9089 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
9090 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
9091 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
9092 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
9093 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
9095 // calculate desired texture sizes
9096 if (vid.support.arb_texture_non_power_of_two)
9098 screentexturewidth = r_refdef.view.width;
9099 screentextureheight = r_refdef.view.height;
9100 bloomtexturewidth = r_bloomstate.bloomwidth;
9101 bloomtextureheight = r_bloomstate.bloomheight;
9105 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
9106 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
9107 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
9108 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
9111 if ((r_hdr.integer || r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > (int)vid.maxtexturesize_2d || r_refdef.view.height > (int)vid.maxtexturesize_2d))
9113 Cvar_SetValueQuick(&r_hdr, 0);
9114 Cvar_SetValueQuick(&r_bloom, 0);
9115 Cvar_SetValueQuick(&r_motionblur, 0);
9116 Cvar_SetValueQuick(&r_damageblur, 0);
9119 if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial)) && !r_bloom.integer && !r_hdr.integer && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0)))
9120 screentexturewidth = screentextureheight = 0;
9121 if (!r_hdr.integer && !r_bloom.integer)
9122 bloomtexturewidth = bloomtextureheight = 0;
9124 // allocate textures as needed
9125 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
9127 if (r_bloomstate.texture_screen)
9128 R_FreeTexture(r_bloomstate.texture_screen);
9129 r_bloomstate.texture_screen = NULL;
9130 r_bloomstate.screentexturewidth = screentexturewidth;
9131 r_bloomstate.screentextureheight = screentextureheight;
9132 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
9133 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCENEAREST | TEXF_CLAMP, -1, NULL);
9135 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
9137 if (r_bloomstate.texture_bloom)
9138 R_FreeTexture(r_bloomstate.texture_bloom);
9139 r_bloomstate.texture_bloom = NULL;
9140 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
9141 r_bloomstate.bloomtextureheight = bloomtextureheight;
9142 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
9143 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
9146 // when doing a reduced render (HDR) we want to use a smaller area
9147 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
9148 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
9149 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
9150 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
9151 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
9153 // set up a texcoord array for the full resolution screen image
9154 // (we have to keep this around to copy back during final render)
9155 r_bloomstate.screentexcoord2f[0] = 0;
9156 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
9157 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
9158 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
9159 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
9160 r_bloomstate.screentexcoord2f[5] = 0;
9161 r_bloomstate.screentexcoord2f[6] = 0;
9162 r_bloomstate.screentexcoord2f[7] = 0;
9164 // set up a texcoord array for the reduced resolution bloom image
9165 // (which will be additive blended over the screen image)
9166 r_bloomstate.bloomtexcoord2f[0] = 0;
9167 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9168 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9169 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9170 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9171 r_bloomstate.bloomtexcoord2f[5] = 0;
9172 r_bloomstate.bloomtexcoord2f[6] = 0;
9173 r_bloomstate.bloomtexcoord2f[7] = 0;
9175 switch(vid.renderpath)
9177 case RENDERPATH_GL11:
9178 case RENDERPATH_GL13:
9179 case RENDERPATH_GL20:
9180 case RENDERPATH_CGGL:
9181 case RENDERPATH_SOFT:
9183 case RENDERPATH_D3D9:
9184 case RENDERPATH_D3D10:
9185 case RENDERPATH_D3D11:
9188 for (i = 0;i < 4;i++)
9190 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
9191 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
9192 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
9193 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
9199 if (r_hdr.integer || r_bloom.integer)
9201 r_bloomstate.enabled = true;
9202 r_bloomstate.hdr = r_hdr.integer != 0;
9205 R_Viewport_InitOrtho(&r_bloomstate.viewport, &identitymatrix, r_refdef.view.x, vid.height - r_bloomstate.bloomheight - r_refdef.view.y, r_bloomstate.bloomwidth, r_bloomstate.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
9208 void R_Bloom_CopyBloomTexture(float colorscale)
9210 r_refdef.stats.bloom++;
9212 // scale down screen texture to the bloom texture size
9214 R_SetViewport(&r_bloomstate.viewport);
9215 GL_BlendFunc(GL_ONE, GL_ZERO);
9216 GL_Color(colorscale, colorscale, colorscale, 1);
9217 // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
9218 switch(vid.renderpath)
9220 case RENDERPATH_GL11:
9221 case RENDERPATH_GL13:
9222 case RENDERPATH_GL20:
9223 case RENDERPATH_CGGL:
9224 case RENDERPATH_SOFT:
9225 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9227 case RENDERPATH_D3D9:
9228 case RENDERPATH_D3D10:
9229 case RENDERPATH_D3D11:
9230 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9233 // TODO: do boxfilter scale-down in shader?
9234 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9235 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9236 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9238 // we now have a bloom image in the framebuffer
9239 // copy it into the bloom image texture for later processing
9240 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
9241 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9244 void R_Bloom_CopyHDRTexture(void)
9246 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
9247 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9250 void R_Bloom_MakeTexture(void)
9253 float xoffset, yoffset, r, brighten;
9255 r_refdef.stats.bloom++;
9257 R_ResetViewRendering2D();
9259 // we have a bloom image in the framebuffer
9261 R_SetViewport(&r_bloomstate.viewport);
9263 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
9266 r = bound(0, r_bloom_colorexponent.value / x, 1);
9267 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9269 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
9270 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9271 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9272 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9274 // copy the vertically blurred bloom view to a texture
9275 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
9276 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9279 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
9280 brighten = r_bloom_brighten.value;
9282 brighten *= r_hdr_range.value;
9283 brighten = sqrt(brighten);
9285 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
9286 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9288 for (dir = 0;dir < 2;dir++)
9290 // blend on at multiple vertical offsets to achieve a vertical blur
9291 // TODO: do offset blends using GLSL
9292 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
9293 GL_BlendFunc(GL_ONE, GL_ZERO);
9294 for (x = -range;x <= range;x++)
9296 if (!dir){xoffset = 0;yoffset = x;}
9297 else {xoffset = x;yoffset = 0;}
9298 xoffset /= (float)r_bloomstate.bloomtexturewidth;
9299 yoffset /= (float)r_bloomstate.bloomtextureheight;
9300 // compute a texcoord array with the specified x and y offset
9301 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
9302 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9303 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9304 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9305 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9306 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
9307 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
9308 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
9309 // this r value looks like a 'dot' particle, fading sharply to
9310 // black at the edges
9311 // (probably not realistic but looks good enough)
9312 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
9313 //r = brighten/(range*2+1);
9314 r = brighten / (range * 2 + 1);
9316 r *= (1 - x*x/(float)(range*range));
9317 GL_Color(r, r, r, 1);
9318 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
9319 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9320 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9321 GL_BlendFunc(GL_ONE, GL_ONE);
9324 // copy the vertically blurred bloom view to a texture
9325 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
9326 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9330 void R_HDR_RenderBloomTexture(void)
9332 int oldwidth, oldheight;
9333 float oldcolorscale;
9334 qboolean oldwaterstate;
9336 oldwaterstate = r_waterstate.enabled;
9337 oldcolorscale = r_refdef.view.colorscale;
9338 oldwidth = r_refdef.view.width;
9339 oldheight = r_refdef.view.height;
9340 r_refdef.view.width = r_bloomstate.bloomwidth;
9341 r_refdef.view.height = r_bloomstate.bloomheight;
9343 if(r_hdr.integer < 2)
9344 r_waterstate.enabled = false;
9346 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
9347 // TODO: add exposure compensation features
9348 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
9350 r_refdef.view.showdebug = false;
9351 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
9353 R_ResetViewRendering3D();
9355 R_ClearScreen(r_refdef.fogenabled);
9356 if (r_timereport_active)
9357 R_TimeReport("HDRclear");
9360 if (r_timereport_active)
9361 R_TimeReport("visibility");
9363 // only do secondary renders with HDR if r_hdr is 2 or higher
9364 r_waterstate.numwaterplanes = 0;
9365 if (r_waterstate.enabled)
9366 R_RenderWaterPlanes();
9368 r_refdef.view.showdebug = true;
9370 r_waterstate.numwaterplanes = 0;
9372 R_ResetViewRendering2D();
9374 R_Bloom_CopyHDRTexture();
9375 R_Bloom_MakeTexture();
9377 // restore the view settings
9378 r_waterstate.enabled = oldwaterstate;
9379 r_refdef.view.width = oldwidth;
9380 r_refdef.view.height = oldheight;
9381 r_refdef.view.colorscale = oldcolorscale;
9383 R_ResetViewRendering3D();
9385 R_ClearScreen(r_refdef.fogenabled);
9386 if (r_timereport_active)
9387 R_TimeReport("viewclear");
9390 static void R_BlendView(void)
9392 unsigned int permutation;
9393 float uservecs[4][4];
9395 switch (vid.renderpath)
9397 case RENDERPATH_GL20:
9398 case RENDERPATH_CGGL:
9399 case RENDERPATH_D3D9:
9400 case RENDERPATH_D3D10:
9401 case RENDERPATH_D3D11:
9402 case RENDERPATH_SOFT:
9404 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
9405 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
9406 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
9407 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
9408 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
9410 if (r_bloomstate.texture_screen)
9412 // make sure the buffer is available
9413 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
9415 R_ResetViewRendering2D();
9417 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
9419 // declare variables
9421 static float avgspeed;
9423 speed = VectorLength(cl.movement_velocity);
9425 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
9426 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
9428 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
9429 speed = bound(0, speed, 1);
9430 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
9432 // calculate values into a standard alpha
9433 cl.motionbluralpha = 1 - exp(-
9435 (r_motionblur.value * speed / 80)
9437 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
9440 max(0.0001, cl.time - cl.oldtime) // fps independent
9443 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
9444 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
9446 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
9448 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9449 GL_Color(1, 1, 1, cl.motionbluralpha);
9450 switch(vid.renderpath)
9452 case RENDERPATH_GL11:
9453 case RENDERPATH_GL13:
9454 case RENDERPATH_GL20:
9455 case RENDERPATH_CGGL:
9456 case RENDERPATH_SOFT:
9457 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9459 case RENDERPATH_D3D9:
9460 case RENDERPATH_D3D10:
9461 case RENDERPATH_D3D11:
9462 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9465 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9466 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9467 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9471 // copy view into the screen texture
9472 R_Mesh_CopyToTexture(r_bloomstate.texture_screen, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
9473 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9475 else if (!r_bloomstate.texture_bloom)
9477 // we may still have to do view tint...
9478 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9480 // apply a color tint to the whole view
9481 R_ResetViewRendering2D();
9482 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9483 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9484 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9485 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9486 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9488 break; // no screen processing, no bloom, skip it
9491 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9493 // render simple bloom effect
9494 // copy the screen and shrink it and darken it for the bloom process
9495 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9496 // make the bloom texture
9497 R_Bloom_MakeTexture();
9500 #if _MSC_VER >= 1400
9501 #define sscanf sscanf_s
9503 memset(uservecs, 0, sizeof(uservecs));
9504 if (r_glsl_postprocess_uservec1_enable.integer)
9505 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9506 if (r_glsl_postprocess_uservec2_enable.integer)
9507 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9508 if (r_glsl_postprocess_uservec3_enable.integer)
9509 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9510 if (r_glsl_postprocess_uservec4_enable.integer)
9511 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9513 R_ResetViewRendering2D();
9514 GL_Color(1, 1, 1, 1);
9515 GL_BlendFunc(GL_ONE, GL_ZERO);
9517 switch(vid.renderpath)
9519 case RENDERPATH_GL20:
9520 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9521 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9522 if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
9523 if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
9524 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
9525 if (r_glsl_permutation->loc_ViewTintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9526 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9527 if (r_glsl_permutation->loc_UserVec1 >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9528 if (r_glsl_permutation->loc_UserVec2 >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9529 if (r_glsl_permutation->loc_UserVec3 >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9530 if (r_glsl_permutation->loc_UserVec4 >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9531 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
9532 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9533 if (r_glsl_permutation->loc_BloomColorSubtract >= 0) qglUniform4fARB(r_glsl_permutation->loc_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9535 case RENDERPATH_CGGL:
9537 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9538 R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9539 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_bloomstate.texture_screen);CHECKCGERROR
9540 if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_bloomstate.texture_bloom );CHECKCGERROR
9541 if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps );CHECKCGERROR
9542 if (r_cg_permutation->fp_ViewTintColor ) cgGLSetParameter4f( r_cg_permutation->fp_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);CHECKCGERROR
9543 if (r_cg_permutation->fp_PixelSize ) cgGLSetParameter2f( r_cg_permutation->fp_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9544 if (r_cg_permutation->fp_UserVec1 ) cgGLSetParameter4f( r_cg_permutation->fp_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);CHECKCGERROR
9545 if (r_cg_permutation->fp_UserVec2 ) cgGLSetParameter4f( r_cg_permutation->fp_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);CHECKCGERROR
9546 if (r_cg_permutation->fp_UserVec3 ) cgGLSetParameter4f( r_cg_permutation->fp_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);CHECKCGERROR
9547 if (r_cg_permutation->fp_UserVec4 ) cgGLSetParameter4f( r_cg_permutation->fp_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);CHECKCGERROR
9548 if (r_cg_permutation->fp_Saturation ) cgGLSetParameter1f( r_cg_permutation->fp_Saturation , r_glsl_saturation.value);CHECKCGERROR
9549 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9550 if (r_cg_permutation->fp_BloomColorSubtract ) cgGLSetParameter4f(r_cg_permutation->fp_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9553 case RENDERPATH_D3D9:
9555 // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
9556 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9557 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9558 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
9559 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
9560 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
9561 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9562 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9563 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9564 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9565 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9566 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9567 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
9568 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9569 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9572 case RENDERPATH_D3D10:
9573 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9575 case RENDERPATH_D3D11:
9576 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9578 case RENDERPATH_SOFT:
9579 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9580 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
9581 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
9582 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
9583 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
9584 DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9585 DPSOFTRAST_Uniform2fARB(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9586 DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9587 DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9588 DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9589 DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9590 DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
9591 DPSOFTRAST_Uniform2fARB(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9592 DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9597 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9598 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9600 case RENDERPATH_GL13:
9601 case RENDERPATH_GL11:
9602 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9604 // apply a color tint to the whole view
9605 R_ResetViewRendering2D();
9606 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9607 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9608 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9609 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9610 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9616 matrix4x4_t r_waterscrollmatrix;
9618 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9620 if (r_refdef.fog_density)
9622 r_refdef.fogcolor[0] = r_refdef.fog_red;
9623 r_refdef.fogcolor[1] = r_refdef.fog_green;
9624 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9626 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9627 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9628 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9629 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9633 VectorCopy(r_refdef.fogcolor, fogvec);
9634 // color.rgb *= ContrastBoost * SceneBrightness;
9635 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9636 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9637 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9638 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9643 void R_UpdateVariables(void)
9647 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9649 r_refdef.farclip = r_farclip_base.value;
9650 if (r_refdef.scene.worldmodel)
9651 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9652 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9654 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9655 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9656 r_refdef.polygonfactor = 0;
9657 r_refdef.polygonoffset = 0;
9658 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9659 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9661 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9662 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9663 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
9664 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9665 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9666 if (FAKELIGHT_ENABLED)
9668 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
9670 if (r_showsurfaces.integer)
9672 r_refdef.scene.rtworld = false;
9673 r_refdef.scene.rtworldshadows = false;
9674 r_refdef.scene.rtdlight = false;
9675 r_refdef.scene.rtdlightshadows = false;
9676 r_refdef.lightmapintensity = 0;
9679 if (gamemode == GAME_NEHAHRA)
9681 if (gl_fogenable.integer)
9683 r_refdef.oldgl_fogenable = true;
9684 r_refdef.fog_density = gl_fogdensity.value;
9685 r_refdef.fog_red = gl_fogred.value;
9686 r_refdef.fog_green = gl_foggreen.value;
9687 r_refdef.fog_blue = gl_fogblue.value;
9688 r_refdef.fog_alpha = 1;
9689 r_refdef.fog_start = 0;
9690 r_refdef.fog_end = gl_skyclip.value;
9691 r_refdef.fog_height = 1<<30;
9692 r_refdef.fog_fadedepth = 128;
9694 else if (r_refdef.oldgl_fogenable)
9696 r_refdef.oldgl_fogenable = false;
9697 r_refdef.fog_density = 0;
9698 r_refdef.fog_red = 0;
9699 r_refdef.fog_green = 0;
9700 r_refdef.fog_blue = 0;
9701 r_refdef.fog_alpha = 0;
9702 r_refdef.fog_start = 0;
9703 r_refdef.fog_end = 0;
9704 r_refdef.fog_height = 1<<30;
9705 r_refdef.fog_fadedepth = 128;
9709 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9710 r_refdef.fog_start = max(0, r_refdef.fog_start);
9711 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9713 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9715 if (r_refdef.fog_density && r_drawfog.integer)
9717 r_refdef.fogenabled = true;
9718 // this is the point where the fog reaches 0.9986 alpha, which we
9719 // consider a good enough cutoff point for the texture
9720 // (0.9986 * 256 == 255.6)
9721 if (r_fog_exp2.integer)
9722 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9724 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9725 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9726 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9727 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9728 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9729 R_BuildFogHeightTexture();
9730 // fog color was already set
9731 // update the fog texture
9732 if (r_refdef.fogmasktable_start != r_refdef.fog_start || r_refdef.fogmasktable_alpha != r_refdef.fog_alpha || r_refdef.fogmasktable_density != r_refdef.fog_density || r_refdef.fogmasktable_range != r_refdef.fogrange)
9733 R_BuildFogTexture();
9734 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9735 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9738 r_refdef.fogenabled = false;
9740 switch(vid.renderpath)
9742 case RENDERPATH_GL20:
9743 case RENDERPATH_CGGL:
9744 case RENDERPATH_D3D9:
9745 case RENDERPATH_D3D10:
9746 case RENDERPATH_D3D11:
9747 case RENDERPATH_SOFT:
9748 if(v_glslgamma.integer && !vid_gammatables_trivial)
9750 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9752 // build GLSL gamma texture
9753 #define RAMPWIDTH 256
9754 unsigned short ramp[RAMPWIDTH * 3];
9755 unsigned char rampbgr[RAMPWIDTH][4];
9758 r_texture_gammaramps_serial = vid_gammatables_serial;
9760 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9761 for(i = 0; i < RAMPWIDTH; ++i)
9763 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9764 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9765 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9768 if (r_texture_gammaramps)
9770 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9774 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9780 // remove GLSL gamma texture
9783 case RENDERPATH_GL13:
9784 case RENDERPATH_GL11:
9789 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9790 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9796 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9797 if( scenetype != r_currentscenetype ) {
9798 // store the old scenetype
9799 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9800 r_currentscenetype = scenetype;
9801 // move in the new scene
9802 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9811 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9813 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9814 if( scenetype == r_currentscenetype ) {
9815 return &r_refdef.scene;
9817 return &r_scenes_store[ scenetype ];
9826 int dpsoftrast_test;
9827 void R_RenderView(void)
9829 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
9831 dpsoftrast_test = r_test.integer;
9833 if (r_timereport_active)
9834 R_TimeReport("start");
9835 r_textureframe++; // used only by R_GetCurrentTexture
9836 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9838 if(R_CompileShader_CheckStaticParms())
9841 if (!r_drawentities.integer)
9842 r_refdef.scene.numentities = 0;
9844 R_AnimCache_ClearCache();
9845 R_FrameData_NewFrame();
9847 /* adjust for stereo display */
9848 if(R_Stereo_Active())
9850 Matrix4x4_CreateFromQuakeEntity(&offsetmatrix, 0, r_stereo_separation.value * (0.5f - r_stereo_side), 0, 0, r_stereo_angle.value * (0.5f - r_stereo_side), 0, 1);
9851 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
9854 if (r_refdef.view.isoverlay)
9856 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9857 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9858 R_TimeReport("depthclear");
9860 r_refdef.view.showdebug = false;
9862 r_waterstate.enabled = false;
9863 r_waterstate.numwaterplanes = 0;
9867 r_refdef.view.matrix = originalmatrix;
9873 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9875 r_refdef.view.matrix = originalmatrix;
9876 return; //Host_Error ("R_RenderView: NULL worldmodel");
9879 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9881 R_RenderView_UpdateViewVectors();
9883 R_Shadow_UpdateWorldLightSelection();
9885 R_Bloom_StartFrame();
9886 R_Water_StartFrame();
9889 if (r_timereport_active)
9890 R_TimeReport("viewsetup");
9892 R_ResetViewRendering3D();
9894 if (r_refdef.view.clear || r_refdef.fogenabled)
9896 R_ClearScreen(r_refdef.fogenabled);
9897 if (r_timereport_active)
9898 R_TimeReport("viewclear");
9900 r_refdef.view.clear = true;
9902 // this produces a bloom texture to be used in R_BlendView() later
9903 if (r_hdr.integer && r_bloomstate.bloomwidth)
9905 R_HDR_RenderBloomTexture();
9906 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9907 r_textureframe++; // used only by R_GetCurrentTexture
9910 r_refdef.view.showdebug = true;
9913 if (r_timereport_active)
9914 R_TimeReport("visibility");
9916 r_waterstate.numwaterplanes = 0;
9917 if (r_waterstate.enabled)
9918 R_RenderWaterPlanes();
9921 r_waterstate.numwaterplanes = 0;
9924 if (r_timereport_active)
9925 R_TimeReport("blendview");
9927 GL_Scissor(0, 0, vid.width, vid.height);
9928 GL_ScissorTest(false);
9930 r_refdef.view.matrix = originalmatrix;
9935 void R_RenderWaterPlanes(void)
9937 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9939 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9940 if (r_timereport_active)
9941 R_TimeReport("waterworld");
9944 // don't let sound skip if going slow
9945 if (r_refdef.scene.extraupdate)
9948 R_DrawModelsAddWaterPlanes();
9949 if (r_timereport_active)
9950 R_TimeReport("watermodels");
9952 if (r_waterstate.numwaterplanes)
9954 R_Water_ProcessPlanes();
9955 if (r_timereport_active)
9956 R_TimeReport("waterscenes");
9960 extern void R_DrawLightningBeams (void);
9961 extern void VM_CL_AddPolygonsToMeshQueue (void);
9962 extern void R_DrawPortals (void);
9963 extern cvar_t cl_locs_show;
9964 static void R_DrawLocs(void);
9965 static void R_DrawEntityBBoxes(void);
9966 static void R_DrawModelDecals(void);
9967 extern void R_DrawModelShadows(void);
9968 extern void R_DrawModelShadowMaps(void);
9969 extern cvar_t cl_decals_newsystem;
9970 extern qboolean r_shadow_usingdeferredprepass;
9971 void R_RenderScene(void)
9973 qboolean shadowmapping = false;
9975 if (r_timereport_active)
9976 R_TimeReport("beginscene");
9978 r_refdef.stats.renders++;
9982 // don't let sound skip if going slow
9983 if (r_refdef.scene.extraupdate)
9986 R_MeshQueue_BeginScene();
9990 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);
9992 if (r_timereport_active)
9993 R_TimeReport("skystartframe");
9995 if (cl.csqc_vidvars.drawworld)
9997 // don't let sound skip if going slow
9998 if (r_refdef.scene.extraupdate)
10001 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
10003 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
10004 if (r_timereport_active)
10005 R_TimeReport("worldsky");
10008 if (R_DrawBrushModelsSky() && r_timereport_active)
10009 R_TimeReport("bmodelsky");
10011 if (skyrendermasked && skyrenderlater)
10013 // we have to force off the water clipping plane while rendering sky
10014 R_SetupView(false);
10017 if (r_timereport_active)
10018 R_TimeReport("sky");
10022 R_AnimCache_CacheVisibleEntities();
10023 if (r_timereport_active)
10024 R_TimeReport("animation");
10026 R_Shadow_PrepareLights();
10027 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
10028 R_Shadow_PrepareModelShadows();
10029 if (r_timereport_active)
10030 R_TimeReport("preparelights");
10032 if (R_Shadow_ShadowMappingEnabled())
10033 shadowmapping = true;
10035 if (r_shadow_usingdeferredprepass)
10036 R_Shadow_DrawPrepass();
10038 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
10040 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
10041 if (r_timereport_active)
10042 R_TimeReport("worlddepth");
10044 if (r_depthfirst.integer >= 2)
10046 R_DrawModelsDepth();
10047 if (r_timereport_active)
10048 R_TimeReport("modeldepth");
10051 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
10053 R_DrawModelShadowMaps();
10054 R_ResetViewRendering3D();
10055 // don't let sound skip if going slow
10056 if (r_refdef.scene.extraupdate)
10060 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
10062 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
10063 if (r_timereport_active)
10064 R_TimeReport("world");
10067 // don't let sound skip if going slow
10068 if (r_refdef.scene.extraupdate)
10072 if (r_timereport_active)
10073 R_TimeReport("models");
10075 // don't let sound skip if going slow
10076 if (r_refdef.scene.extraupdate)
10079 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
10081 R_DrawModelShadows();
10082 R_ResetViewRendering3D();
10083 // don't let sound skip if going slow
10084 if (r_refdef.scene.extraupdate)
10088 if (!r_shadow_usingdeferredprepass)
10090 R_Shadow_DrawLights();
10091 if (r_timereport_active)
10092 R_TimeReport("rtlights");
10095 // don't let sound skip if going slow
10096 if (r_refdef.scene.extraupdate)
10099 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
10101 R_DrawModelShadows();
10102 R_ResetViewRendering3D();
10103 // don't let sound skip if going slow
10104 if (r_refdef.scene.extraupdate)
10108 if (cl.csqc_vidvars.drawworld)
10110 if (cl_decals_newsystem.integer)
10112 R_DrawModelDecals();
10113 if (r_timereport_active)
10114 R_TimeReport("modeldecals");
10119 if (r_timereport_active)
10120 R_TimeReport("decals");
10124 if (r_timereport_active)
10125 R_TimeReport("particles");
10127 R_DrawExplosions();
10128 if (r_timereport_active)
10129 R_TimeReport("explosions");
10131 R_DrawLightningBeams();
10132 if (r_timereport_active)
10133 R_TimeReport("lightning");
10136 VM_CL_AddPolygonsToMeshQueue();
10138 if (r_refdef.view.showdebug)
10140 if (cl_locs_show.integer)
10143 if (r_timereport_active)
10144 R_TimeReport("showlocs");
10147 if (r_drawportals.integer)
10150 if (r_timereport_active)
10151 R_TimeReport("portals");
10154 if (r_showbboxes.value > 0)
10156 R_DrawEntityBBoxes();
10157 if (r_timereport_active)
10158 R_TimeReport("bboxes");
10162 R_MeshQueue_RenderTransparent();
10163 if (r_timereport_active)
10164 R_TimeReport("drawtrans");
10166 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))
10168 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
10169 if (r_timereport_active)
10170 R_TimeReport("worlddebug");
10171 R_DrawModelsDebug();
10172 if (r_timereport_active)
10173 R_TimeReport("modeldebug");
10176 if (cl.csqc_vidvars.drawworld)
10178 R_Shadow_DrawCoronas();
10179 if (r_timereport_active)
10180 R_TimeReport("coronas");
10185 GL_DepthTest(false);
10186 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10187 GL_Color(1, 1, 1, 1);
10188 qglBegin(GL_POLYGON);
10189 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
10190 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
10191 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
10192 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
10194 qglBegin(GL_POLYGON);
10195 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]);
10196 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]);
10197 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]);
10198 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]);
10200 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10204 // don't let sound skip if going slow
10205 if (r_refdef.scene.extraupdate)
10208 R_ResetViewRendering2D();
10211 static const unsigned short bboxelements[36] =
10221 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
10224 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
10226 RSurf_ActiveWorldEntity();
10228 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10229 GL_DepthMask(false);
10230 GL_DepthRange(0, 1);
10231 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10232 // R_Mesh_ResetTextureState();
10234 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
10235 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
10236 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
10237 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
10238 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
10239 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
10240 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
10241 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
10242 R_FillColors(color4f, 8, cr, cg, cb, ca);
10243 if (r_refdef.fogenabled)
10245 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
10247 f1 = RSurf_FogVertex(v);
10249 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
10250 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
10251 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
10254 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
10255 R_Mesh_ResetTextureState();
10256 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10257 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
10260 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10264 prvm_edict_t *edict;
10265 prvm_prog_t *prog_save = prog;
10267 // this function draws bounding boxes of server entities
10271 GL_CullFace(GL_NONE);
10272 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10276 for (i = 0;i < numsurfaces;i++)
10278 edict = PRVM_EDICT_NUM(surfacelist[i]);
10279 switch ((int)edict->fields.server->solid)
10281 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
10282 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
10283 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
10284 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
10285 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
10286 default: Vector4Set(color, 0, 0, 0, 0.50);break;
10288 color[3] *= r_showbboxes.value;
10289 color[3] = bound(0, color[3], 1);
10290 GL_DepthTest(!r_showdisabledepthtest.integer);
10291 GL_CullFace(r_refdef.view.cullface_front);
10292 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
10298 static void R_DrawEntityBBoxes(void)
10301 prvm_edict_t *edict;
10303 prvm_prog_t *prog_save = prog;
10305 // this function draws bounding boxes of server entities
10311 for (i = 0;i < prog->num_edicts;i++)
10313 edict = PRVM_EDICT_NUM(i);
10314 if (edict->priv.server->free)
10316 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
10317 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
10319 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
10321 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
10322 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
10328 static const int nomodelelement3i[24] =
10340 static const unsigned short nomodelelement3s[24] =
10352 static const float nomodelvertex3f[6*3] =
10362 static const float nomodelcolor4f[6*4] =
10364 0.0f, 0.0f, 0.5f, 1.0f,
10365 0.0f, 0.0f, 0.5f, 1.0f,
10366 0.0f, 0.5f, 0.0f, 1.0f,
10367 0.0f, 0.5f, 0.0f, 1.0f,
10368 0.5f, 0.0f, 0.0f, 1.0f,
10369 0.5f, 0.0f, 0.0f, 1.0f
10372 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10376 float color4f[6*4];
10378 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);
10380 // this is only called once per entity so numsurfaces is always 1, and
10381 // surfacelist is always {0}, so this code does not handle batches
10383 if (rsurface.ent_flags & RENDER_ADDITIVE)
10385 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
10386 GL_DepthMask(false);
10388 else if (rsurface.colormod[3] < 1)
10390 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10391 GL_DepthMask(false);
10395 GL_BlendFunc(GL_ONE, GL_ZERO);
10396 GL_DepthMask(true);
10398 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
10399 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
10400 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
10401 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
10402 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
10403 for (i = 0, c = color4f;i < 6;i++, c += 4)
10405 c[0] *= rsurface.colormod[0];
10406 c[1] *= rsurface.colormod[1];
10407 c[2] *= rsurface.colormod[2];
10408 c[3] *= rsurface.colormod[3];
10410 if (r_refdef.fogenabled)
10412 for (i = 0, c = color4f;i < 6;i++, c += 4)
10414 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
10416 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
10417 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
10418 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
10421 // R_Mesh_ResetTextureState();
10422 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10423 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
10424 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
10427 void R_DrawNoModel(entity_render_t *ent)
10430 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
10431 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
10432 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
10434 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
10437 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
10439 vec3_t right1, right2, diff, normal;
10441 VectorSubtract (org2, org1, normal);
10443 // calculate 'right' vector for start
10444 VectorSubtract (r_refdef.view.origin, org1, diff);
10445 CrossProduct (normal, diff, right1);
10446 VectorNormalize (right1);
10448 // calculate 'right' vector for end
10449 VectorSubtract (r_refdef.view.origin, org2, diff);
10450 CrossProduct (normal, diff, right2);
10451 VectorNormalize (right2);
10453 vert[ 0] = org1[0] + width * right1[0];
10454 vert[ 1] = org1[1] + width * right1[1];
10455 vert[ 2] = org1[2] + width * right1[2];
10456 vert[ 3] = org1[0] - width * right1[0];
10457 vert[ 4] = org1[1] - width * right1[1];
10458 vert[ 5] = org1[2] - width * right1[2];
10459 vert[ 6] = org2[0] - width * right2[0];
10460 vert[ 7] = org2[1] - width * right2[1];
10461 vert[ 8] = org2[2] - width * right2[2];
10462 vert[ 9] = org2[0] + width * right2[0];
10463 vert[10] = org2[1] + width * right2[1];
10464 vert[11] = org2[2] + width * right2[2];
10467 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)
10469 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
10470 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
10471 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
10472 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
10473 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
10474 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
10475 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
10476 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
10477 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
10478 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
10479 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
10480 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
10483 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
10488 VectorSet(v, x, y, z);
10489 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
10490 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
10492 if (i == mesh->numvertices)
10494 if (mesh->numvertices < mesh->maxvertices)
10496 VectorCopy(v, vertex3f);
10497 mesh->numvertices++;
10499 return mesh->numvertices;
10505 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
10508 int *e, element[3];
10509 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10510 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10511 e = mesh->element3i + mesh->numtriangles * 3;
10512 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
10514 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
10515 if (mesh->numtriangles < mesh->maxtriangles)
10520 mesh->numtriangles++;
10522 element[1] = element[2];
10526 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
10529 int *e, element[3];
10530 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10531 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10532 e = mesh->element3i + mesh->numtriangles * 3;
10533 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10535 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10536 if (mesh->numtriangles < mesh->maxtriangles)
10541 mesh->numtriangles++;
10543 element[1] = element[2];
10547 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10548 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10550 int planenum, planenum2;
10553 mplane_t *plane, *plane2;
10555 double temppoints[2][256*3];
10556 // figure out how large a bounding box we need to properly compute this brush
10558 for (w = 0;w < numplanes;w++)
10559 maxdist = max(maxdist, fabs(planes[w].dist));
10560 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10561 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10562 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10566 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10567 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10569 if (planenum2 == planenum)
10571 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);
10574 if (tempnumpoints < 3)
10576 // generate elements forming a triangle fan for this polygon
10577 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10581 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)
10583 texturelayer_t *layer;
10584 layer = t->currentlayers + t->currentnumlayers++;
10585 layer->type = type;
10586 layer->depthmask = depthmask;
10587 layer->blendfunc1 = blendfunc1;
10588 layer->blendfunc2 = blendfunc2;
10589 layer->texture = texture;
10590 layer->texmatrix = *matrix;
10591 layer->color[0] = r;
10592 layer->color[1] = g;
10593 layer->color[2] = b;
10594 layer->color[3] = a;
10597 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10599 if(parms[0] == 0 && parms[1] == 0)
10601 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10602 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10607 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10610 index = parms[2] + r_refdef.scene.time * parms[3];
10611 index -= floor(index);
10612 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10615 case Q3WAVEFUNC_NONE:
10616 case Q3WAVEFUNC_NOISE:
10617 case Q3WAVEFUNC_COUNT:
10620 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10621 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10622 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10623 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10624 case Q3WAVEFUNC_TRIANGLE:
10626 f = index - floor(index);
10629 else if (index < 2)
10631 else if (index < 3)
10637 f = parms[0] + parms[1] * f;
10638 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10639 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10643 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10648 matrix4x4_t matrix, temp;
10649 switch(tcmod->tcmod)
10651 case Q3TCMOD_COUNT:
10653 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10654 matrix = r_waterscrollmatrix;
10656 matrix = identitymatrix;
10658 case Q3TCMOD_ENTITYTRANSLATE:
10659 // this is used in Q3 to allow the gamecode to control texcoord
10660 // scrolling on the entity, which is not supported in darkplaces yet.
10661 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10663 case Q3TCMOD_ROTATE:
10664 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10665 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10666 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10668 case Q3TCMOD_SCALE:
10669 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10671 case Q3TCMOD_SCROLL:
10672 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10674 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10675 w = (int) tcmod->parms[0];
10676 h = (int) tcmod->parms[1];
10677 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10679 idx = (int) floor(f * w * h);
10680 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10682 case Q3TCMOD_STRETCH:
10683 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10684 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10686 case Q3TCMOD_TRANSFORM:
10687 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
10688 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
10689 VectorSet(tcmat + 6, 0 , 0 , 1);
10690 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
10691 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10693 case Q3TCMOD_TURBULENT:
10694 // this is handled in the RSurf_PrepareVertices function
10695 matrix = identitymatrix;
10699 Matrix4x4_Concat(texmatrix, &matrix, &temp);
10702 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10704 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10705 char name[MAX_QPATH];
10706 skinframe_t *skinframe;
10707 unsigned char pixels[296*194];
10708 strlcpy(cache->name, skinname, sizeof(cache->name));
10709 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10710 if (developer_loading.integer)
10711 Con_Printf("loading %s\n", name);
10712 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10713 if (!skinframe || !skinframe->base)
10716 fs_offset_t filesize;
10718 f = FS_LoadFile(name, tempmempool, true, &filesize);
10721 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10722 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10726 cache->skinframe = skinframe;
10729 texture_t *R_GetCurrentTexture(texture_t *t)
10732 const entity_render_t *ent = rsurface.entity;
10733 dp_model_t *model = ent->model;
10734 q3shaderinfo_layer_tcmod_t *tcmod;
10736 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10737 return t->currentframe;
10738 t->update_lastrenderframe = r_textureframe;
10739 t->update_lastrenderentity = (void *)ent;
10741 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10742 t->camera_entity = ent->entitynumber;
10744 t->camera_entity = 0;
10746 // switch to an alternate material if this is a q1bsp animated material
10748 texture_t *texture = t;
10749 int s = rsurface.ent_skinnum;
10750 if ((unsigned int)s >= (unsigned int)model->numskins)
10752 if (model->skinscenes)
10754 if (model->skinscenes[s].framecount > 1)
10755 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10757 s = model->skinscenes[s].firstframe;
10760 t = t + s * model->num_surfaces;
10763 // use an alternate animation if the entity's frame is not 0,
10764 // and only if the texture has an alternate animation
10765 if (rsurface.ent_alttextures && t->anim_total[1])
10766 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10768 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10770 texture->currentframe = t;
10773 // update currentskinframe to be a qw skin or animation frame
10774 if (rsurface.ent_qwskin >= 0)
10776 i = rsurface.ent_qwskin;
10777 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10779 r_qwskincache_size = cl.maxclients;
10781 Mem_Free(r_qwskincache);
10782 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10784 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10785 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10786 t->currentskinframe = r_qwskincache[i].skinframe;
10787 if (t->currentskinframe == NULL)
10788 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10790 else if (t->numskinframes >= 2)
10791 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10792 if (t->backgroundnumskinframes >= 2)
10793 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10795 t->currentmaterialflags = t->basematerialflags;
10796 t->currentalpha = rsurface.colormod[3];
10797 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10798 t->currentalpha *= r_wateralpha.value;
10799 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10800 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10801 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10802 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10803 if (!(rsurface.ent_flags & RENDER_LIGHT))
10804 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10805 else if (FAKELIGHT_ENABLED)
10807 // no modellight if using fakelight for the map
10809 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10811 // pick a model lighting mode
10812 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10813 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10815 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10817 if (rsurface.ent_flags & RENDER_ADDITIVE)
10818 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10819 else if (t->currentalpha < 1)
10820 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10821 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10822 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10823 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10824 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10825 if (t->backgroundnumskinframes)
10826 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10827 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10829 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10830 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10833 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10834 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10835 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10837 // there is no tcmod
10838 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10840 t->currenttexmatrix = r_waterscrollmatrix;
10841 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10843 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10845 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10846 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10849 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10850 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10851 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10852 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10854 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10855 if (t->currentskinframe->qpixels)
10856 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10857 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10858 if (!t->basetexture)
10859 t->basetexture = r_texture_notexture;
10860 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10861 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10862 t->nmaptexture = t->currentskinframe->nmap;
10863 if (!t->nmaptexture)
10864 t->nmaptexture = r_texture_blanknormalmap;
10865 t->glosstexture = r_texture_black;
10866 t->glowtexture = t->currentskinframe->glow;
10867 t->fogtexture = t->currentskinframe->fog;
10868 t->reflectmasktexture = t->currentskinframe->reflect;
10869 if (t->backgroundnumskinframes)
10871 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10872 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10873 t->backgroundglosstexture = r_texture_black;
10874 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10875 if (!t->backgroundnmaptexture)
10876 t->backgroundnmaptexture = r_texture_blanknormalmap;
10880 t->backgroundbasetexture = r_texture_white;
10881 t->backgroundnmaptexture = r_texture_blanknormalmap;
10882 t->backgroundglosstexture = r_texture_black;
10883 t->backgroundglowtexture = NULL;
10885 t->specularpower = r_shadow_glossexponent.value;
10886 // TODO: store reference values for these in the texture?
10887 t->specularscale = 0;
10888 if (r_shadow_gloss.integer > 0)
10890 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10892 if (r_shadow_glossintensity.value > 0)
10894 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10895 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10896 t->specularscale = r_shadow_glossintensity.value;
10899 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10901 t->glosstexture = r_texture_white;
10902 t->backgroundglosstexture = r_texture_white;
10903 t->specularscale = r_shadow_gloss2intensity.value;
10904 t->specularpower = r_shadow_gloss2exponent.value;
10907 t->specularscale *= t->specularscalemod;
10908 t->specularpower *= t->specularpowermod;
10910 // lightmaps mode looks bad with dlights using actual texturing, so turn
10911 // off the colormap and glossmap, but leave the normalmap on as it still
10912 // accurately represents the shading involved
10913 if (gl_lightmaps.integer)
10915 t->basetexture = r_texture_grey128;
10916 t->pantstexture = r_texture_black;
10917 t->shirttexture = r_texture_black;
10918 t->nmaptexture = r_texture_blanknormalmap;
10919 t->glosstexture = r_texture_black;
10920 t->glowtexture = NULL;
10921 t->fogtexture = NULL;
10922 t->reflectmasktexture = NULL;
10923 t->backgroundbasetexture = NULL;
10924 t->backgroundnmaptexture = r_texture_blanknormalmap;
10925 t->backgroundglosstexture = r_texture_black;
10926 t->backgroundglowtexture = NULL;
10927 t->specularscale = 0;
10928 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10931 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10932 VectorClear(t->dlightcolor);
10933 t->currentnumlayers = 0;
10934 if (t->currentmaterialflags & MATERIALFLAG_WALL)
10936 int blendfunc1, blendfunc2;
10937 qboolean depthmask;
10938 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10940 blendfunc1 = GL_SRC_ALPHA;
10941 blendfunc2 = GL_ONE;
10943 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10945 blendfunc1 = GL_SRC_ALPHA;
10946 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10948 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10950 blendfunc1 = t->customblendfunc[0];
10951 blendfunc2 = t->customblendfunc[1];
10955 blendfunc1 = GL_ONE;
10956 blendfunc2 = GL_ZERO;
10958 // don't colormod evilblend textures
10959 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10960 VectorSet(t->lightmapcolor, 1, 1, 1);
10961 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10962 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10964 // fullbright is not affected by r_refdef.lightmapintensity
10965 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]);
10966 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10967 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]);
10968 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10969 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]);
10973 vec3_t ambientcolor;
10975 // set the color tint used for lights affecting this surface
10976 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10978 // q3bsp has no lightmap updates, so the lightstylevalue that
10979 // would normally be baked into the lightmap must be
10980 // applied to the color
10981 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10982 if (model->type == mod_brushq3)
10983 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10984 colorscale *= r_refdef.lightmapintensity;
10985 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10986 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10987 // basic lit geometry
10988 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]);
10989 // add pants/shirt if needed
10990 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10991 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]);
10992 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10993 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]);
10994 // now add ambient passes if needed
10995 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10997 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]);
10998 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10999 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]);
11000 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
11001 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]);
11004 if (t->glowtexture != NULL && !gl_lightmaps.integer)
11005 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]);
11006 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
11008 // if this is opaque use alpha blend which will darken the earlier
11011 // if this is an alpha blended material, all the earlier passes
11012 // were darkened by fog already, so we only need to add the fog
11013 // color ontop through the fog mask texture
11015 // if this is an additive blended material, all the earlier passes
11016 // were darkened by fog already, and we should not add fog color
11017 // (because the background was not darkened, there is no fog color
11018 // that was lost behind it).
11019 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]);
11023 return t->currentframe;
11026 rsurfacestate_t rsurface;
11028 void RSurf_ActiveWorldEntity(void)
11030 dp_model_t *model = r_refdef.scene.worldmodel;
11031 //if (rsurface.entity == r_refdef.scene.worldentity)
11033 rsurface.entity = r_refdef.scene.worldentity;
11034 rsurface.skeleton = NULL;
11035 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
11036 rsurface.ent_skinnum = 0;
11037 rsurface.ent_qwskin = -1;
11038 rsurface.ent_shadertime = 0;
11039 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
11040 rsurface.matrix = identitymatrix;
11041 rsurface.inversematrix = identitymatrix;
11042 rsurface.matrixscale = 1;
11043 rsurface.inversematrixscale = 1;
11044 R_EntityMatrix(&identitymatrix);
11045 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
11046 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
11047 rsurface.fograngerecip = r_refdef.fograngerecip;
11048 rsurface.fogheightfade = r_refdef.fogheightfade;
11049 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
11050 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11051 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11052 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11053 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11054 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11055 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11056 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
11057 rsurface.colormod[3] = 1;
11058 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);
11059 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11060 rsurface.frameblend[0].lerp = 1;
11061 rsurface.ent_alttextures = false;
11062 rsurface.basepolygonfactor = r_refdef.polygonfactor;
11063 rsurface.basepolygonoffset = r_refdef.polygonoffset;
11064 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
11065 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11066 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
11067 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
11068 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11069 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
11070 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
11071 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11072 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
11073 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
11074 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11075 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
11076 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
11077 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11078 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11079 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
11080 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11081 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11082 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
11083 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11084 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11085 rsurface.modelelement3i = model->surfmesh.data_element3i;
11086 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11087 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11088 rsurface.modelelement3s = model->surfmesh.data_element3s;
11089 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11090 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11091 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11092 rsurface.modelnumvertices = model->surfmesh.num_vertices;
11093 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11094 rsurface.modelsurfaces = model->data_surfaces;
11095 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
11096 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
11097 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
11098 rsurface.modelgeneratedvertex = false;
11099 rsurface.batchgeneratedvertex = false;
11100 rsurface.batchfirstvertex = 0;
11101 rsurface.batchnumvertices = 0;
11102 rsurface.batchfirsttriangle = 0;
11103 rsurface.batchnumtriangles = 0;
11104 rsurface.batchvertex3f = NULL;
11105 rsurface.batchvertex3f_vertexbuffer = NULL;
11106 rsurface.batchvertex3f_bufferoffset = 0;
11107 rsurface.batchsvector3f = NULL;
11108 rsurface.batchsvector3f_vertexbuffer = NULL;
11109 rsurface.batchsvector3f_bufferoffset = 0;
11110 rsurface.batchtvector3f = NULL;
11111 rsurface.batchtvector3f_vertexbuffer = NULL;
11112 rsurface.batchtvector3f_bufferoffset = 0;
11113 rsurface.batchnormal3f = NULL;
11114 rsurface.batchnormal3f_vertexbuffer = NULL;
11115 rsurface.batchnormal3f_bufferoffset = 0;
11116 rsurface.batchlightmapcolor4f = NULL;
11117 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11118 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11119 rsurface.batchtexcoordtexture2f = NULL;
11120 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11121 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11122 rsurface.batchtexcoordlightmap2f = NULL;
11123 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11124 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11125 rsurface.batchvertexmesh = NULL;
11126 rsurface.batchvertexmeshbuffer = NULL;
11127 rsurface.batchvertex3fbuffer = NULL;
11128 rsurface.batchelement3i = NULL;
11129 rsurface.batchelement3i_indexbuffer = NULL;
11130 rsurface.batchelement3i_bufferoffset = 0;
11131 rsurface.batchelement3s = NULL;
11132 rsurface.batchelement3s_indexbuffer = NULL;
11133 rsurface.batchelement3s_bufferoffset = 0;
11134 rsurface.passcolor4f = NULL;
11135 rsurface.passcolor4f_vertexbuffer = NULL;
11136 rsurface.passcolor4f_bufferoffset = 0;
11139 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
11141 dp_model_t *model = ent->model;
11142 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
11144 rsurface.entity = (entity_render_t *)ent;
11145 rsurface.skeleton = ent->skeleton;
11146 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
11147 rsurface.ent_skinnum = ent->skinnum;
11148 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;
11149 rsurface.ent_shadertime = ent->shadertime;
11150 rsurface.ent_flags = ent->flags;
11151 rsurface.matrix = ent->matrix;
11152 rsurface.inversematrix = ent->inversematrix;
11153 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11154 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11155 R_EntityMatrix(&rsurface.matrix);
11156 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11157 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11158 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11159 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11160 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11161 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11162 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
11163 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
11164 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
11165 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
11166 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
11167 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
11168 rsurface.colormod[3] = ent->alpha;
11169 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
11170 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
11171 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
11172 rsurface.basepolygonfactor = r_refdef.polygonfactor;
11173 rsurface.basepolygonoffset = r_refdef.polygonoffset;
11174 if (ent->model->brush.submodel && !prepass)
11176 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
11177 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
11179 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
11181 if (ent->animcache_vertex3f)
11183 rsurface.modelvertex3f = ent->animcache_vertex3f;
11184 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
11185 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
11186 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
11187 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
11188 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
11189 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
11191 else if (wanttangents)
11193 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11194 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11195 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11196 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11197 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
11198 rsurface.modelvertexmesh = NULL;
11199 rsurface.modelvertexmeshbuffer = NULL;
11200 rsurface.modelvertex3fbuffer = NULL;
11202 else if (wantnormals)
11204 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11205 rsurface.modelsvector3f = NULL;
11206 rsurface.modeltvector3f = NULL;
11207 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11208 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
11209 rsurface.modelvertexmesh = NULL;
11210 rsurface.modelvertexmeshbuffer = NULL;
11211 rsurface.modelvertex3fbuffer = NULL;
11215 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11216 rsurface.modelsvector3f = NULL;
11217 rsurface.modeltvector3f = NULL;
11218 rsurface.modelnormal3f = NULL;
11219 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
11220 rsurface.modelvertexmesh = NULL;
11221 rsurface.modelvertexmeshbuffer = NULL;
11222 rsurface.modelvertex3fbuffer = NULL;
11224 rsurface.modelvertex3f_vertexbuffer = 0;
11225 rsurface.modelvertex3f_bufferoffset = 0;
11226 rsurface.modelsvector3f_vertexbuffer = 0;
11227 rsurface.modelsvector3f_bufferoffset = 0;
11228 rsurface.modeltvector3f_vertexbuffer = 0;
11229 rsurface.modeltvector3f_bufferoffset = 0;
11230 rsurface.modelnormal3f_vertexbuffer = 0;
11231 rsurface.modelnormal3f_bufferoffset = 0;
11232 rsurface.modelgeneratedvertex = true;
11236 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
11237 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11238 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
11239 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
11240 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11241 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
11242 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
11243 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11244 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
11245 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
11246 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11247 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
11248 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
11249 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
11250 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
11251 rsurface.modelgeneratedvertex = false;
11253 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
11254 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11255 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11256 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
11257 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11258 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11259 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
11260 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11261 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11262 rsurface.modelelement3i = model->surfmesh.data_element3i;
11263 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11264 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11265 rsurface.modelelement3s = model->surfmesh.data_element3s;
11266 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11267 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11268 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11269 rsurface.modelnumvertices = model->surfmesh.num_vertices;
11270 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11271 rsurface.modelsurfaces = model->data_surfaces;
11272 rsurface.batchgeneratedvertex = false;
11273 rsurface.batchfirstvertex = 0;
11274 rsurface.batchnumvertices = 0;
11275 rsurface.batchfirsttriangle = 0;
11276 rsurface.batchnumtriangles = 0;
11277 rsurface.batchvertex3f = NULL;
11278 rsurface.batchvertex3f_vertexbuffer = NULL;
11279 rsurface.batchvertex3f_bufferoffset = 0;
11280 rsurface.batchsvector3f = NULL;
11281 rsurface.batchsvector3f_vertexbuffer = NULL;
11282 rsurface.batchsvector3f_bufferoffset = 0;
11283 rsurface.batchtvector3f = NULL;
11284 rsurface.batchtvector3f_vertexbuffer = NULL;
11285 rsurface.batchtvector3f_bufferoffset = 0;
11286 rsurface.batchnormal3f = NULL;
11287 rsurface.batchnormal3f_vertexbuffer = NULL;
11288 rsurface.batchnormal3f_bufferoffset = 0;
11289 rsurface.batchlightmapcolor4f = NULL;
11290 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11291 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11292 rsurface.batchtexcoordtexture2f = NULL;
11293 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11294 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11295 rsurface.batchtexcoordlightmap2f = NULL;
11296 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11297 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11298 rsurface.batchvertexmesh = NULL;
11299 rsurface.batchvertexmeshbuffer = NULL;
11300 rsurface.batchvertex3fbuffer = NULL;
11301 rsurface.batchelement3i = NULL;
11302 rsurface.batchelement3i_indexbuffer = NULL;
11303 rsurface.batchelement3i_bufferoffset = 0;
11304 rsurface.batchelement3s = NULL;
11305 rsurface.batchelement3s_indexbuffer = NULL;
11306 rsurface.batchelement3s_bufferoffset = 0;
11307 rsurface.passcolor4f = NULL;
11308 rsurface.passcolor4f_vertexbuffer = NULL;
11309 rsurface.passcolor4f_bufferoffset = 0;
11312 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)
11314 rsurface.entity = r_refdef.scene.worldentity;
11315 rsurface.skeleton = NULL;
11316 rsurface.ent_skinnum = 0;
11317 rsurface.ent_qwskin = -1;
11318 rsurface.ent_shadertime = shadertime;
11319 rsurface.ent_flags = entflags;
11320 rsurface.modelnumvertices = numvertices;
11321 rsurface.modelnumtriangles = numtriangles;
11322 rsurface.matrix = *matrix;
11323 rsurface.inversematrix = *inversematrix;
11324 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11325 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11326 R_EntityMatrix(&rsurface.matrix);
11327 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11328 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11329 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11330 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11331 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11332 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11333 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11334 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11335 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11336 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11337 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11338 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
11339 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);
11340 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11341 rsurface.frameblend[0].lerp = 1;
11342 rsurface.ent_alttextures = false;
11343 rsurface.basepolygonfactor = r_refdef.polygonfactor;
11344 rsurface.basepolygonoffset = r_refdef.polygonoffset;
11347 rsurface.modelvertex3f = (float *)vertex3f;
11348 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11349 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11350 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11352 else if (wantnormals)
11354 rsurface.modelvertex3f = (float *)vertex3f;
11355 rsurface.modelsvector3f = NULL;
11356 rsurface.modeltvector3f = NULL;
11357 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11361 rsurface.modelvertex3f = (float *)vertex3f;
11362 rsurface.modelsvector3f = NULL;
11363 rsurface.modeltvector3f = NULL;
11364 rsurface.modelnormal3f = NULL;
11366 rsurface.modelvertexmesh = NULL;
11367 rsurface.modelvertexmeshbuffer = NULL;
11368 rsurface.modelvertex3fbuffer = NULL;
11369 rsurface.modelvertex3f_vertexbuffer = 0;
11370 rsurface.modelvertex3f_bufferoffset = 0;
11371 rsurface.modelsvector3f_vertexbuffer = 0;
11372 rsurface.modelsvector3f_bufferoffset = 0;
11373 rsurface.modeltvector3f_vertexbuffer = 0;
11374 rsurface.modeltvector3f_bufferoffset = 0;
11375 rsurface.modelnormal3f_vertexbuffer = 0;
11376 rsurface.modelnormal3f_bufferoffset = 0;
11377 rsurface.modelgeneratedvertex = true;
11378 rsurface.modellightmapcolor4f = (float *)color4f;
11379 rsurface.modellightmapcolor4f_vertexbuffer = 0;
11380 rsurface.modellightmapcolor4f_bufferoffset = 0;
11381 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
11382 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
11383 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
11384 rsurface.modeltexcoordlightmap2f = NULL;
11385 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
11386 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
11387 rsurface.modelelement3i = (int *)element3i;
11388 rsurface.modelelement3i_indexbuffer = NULL;
11389 rsurface.modelelement3i_bufferoffset = 0;
11390 rsurface.modelelement3s = (unsigned short *)element3s;
11391 rsurface.modelelement3s_indexbuffer = NULL;
11392 rsurface.modelelement3s_bufferoffset = 0;
11393 rsurface.modellightmapoffsets = NULL;
11394 rsurface.modelsurfaces = NULL;
11395 rsurface.batchgeneratedvertex = false;
11396 rsurface.batchfirstvertex = 0;
11397 rsurface.batchnumvertices = 0;
11398 rsurface.batchfirsttriangle = 0;
11399 rsurface.batchnumtriangles = 0;
11400 rsurface.batchvertex3f = NULL;
11401 rsurface.batchvertex3f_vertexbuffer = NULL;
11402 rsurface.batchvertex3f_bufferoffset = 0;
11403 rsurface.batchsvector3f = NULL;
11404 rsurface.batchsvector3f_vertexbuffer = NULL;
11405 rsurface.batchsvector3f_bufferoffset = 0;
11406 rsurface.batchtvector3f = NULL;
11407 rsurface.batchtvector3f_vertexbuffer = NULL;
11408 rsurface.batchtvector3f_bufferoffset = 0;
11409 rsurface.batchnormal3f = NULL;
11410 rsurface.batchnormal3f_vertexbuffer = NULL;
11411 rsurface.batchnormal3f_bufferoffset = 0;
11412 rsurface.batchlightmapcolor4f = NULL;
11413 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11414 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11415 rsurface.batchtexcoordtexture2f = NULL;
11416 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11417 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11418 rsurface.batchtexcoordlightmap2f = NULL;
11419 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11420 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11421 rsurface.batchvertexmesh = NULL;
11422 rsurface.batchvertexmeshbuffer = NULL;
11423 rsurface.batchvertex3fbuffer = NULL;
11424 rsurface.batchelement3i = NULL;
11425 rsurface.batchelement3i_indexbuffer = NULL;
11426 rsurface.batchelement3i_bufferoffset = 0;
11427 rsurface.batchelement3s = NULL;
11428 rsurface.batchelement3s_indexbuffer = NULL;
11429 rsurface.batchelement3s_bufferoffset = 0;
11430 rsurface.passcolor4f = NULL;
11431 rsurface.passcolor4f_vertexbuffer = NULL;
11432 rsurface.passcolor4f_bufferoffset = 0;
11434 if (rsurface.modelnumvertices && rsurface.modelelement3i)
11436 if ((wantnormals || wanttangents) && !normal3f)
11438 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11439 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
11441 if (wanttangents && !svector3f)
11443 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11444 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11445 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
11450 float RSurf_FogPoint(const float *v)
11452 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11453 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11454 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11455 float FogHeightFade = r_refdef.fogheightfade;
11457 unsigned int fogmasktableindex;
11458 if (r_refdef.fogplaneviewabove)
11459 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11461 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11462 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11463 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11466 float RSurf_FogVertex(const float *v)
11468 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11469 float FogPlaneViewDist = rsurface.fogplaneviewdist;
11470 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11471 float FogHeightFade = rsurface.fogheightfade;
11473 unsigned int fogmasktableindex;
11474 if (r_refdef.fogplaneviewabove)
11475 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11477 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11478 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11479 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11482 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11485 for (i = 0;i < numelements;i++)
11486 outelement3i[i] = inelement3i[i] + adjust;
11489 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11490 extern cvar_t gl_vbo;
11491 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11499 int surfacefirsttriangle;
11500 int surfacenumtriangles;
11501 int surfacefirstvertex;
11502 int surfaceendvertex;
11503 int surfacenumvertices;
11504 int batchnumvertices;
11505 int batchnumtriangles;
11509 qboolean dynamicvertex;
11513 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11514 float waveparms[4];
11515 q3shaderinfo_deform_t *deform;
11516 const msurface_t *surface, *firstsurface;
11517 r_vertexmesh_t *vertexmesh;
11518 if (!texturenumsurfaces)
11520 // find vertex range of this surface batch
11522 firstsurface = texturesurfacelist[0];
11523 firsttriangle = firstsurface->num_firsttriangle;
11524 batchnumvertices = 0;
11525 batchnumtriangles = 0;
11526 firstvertex = endvertex = firstsurface->num_firstvertex;
11527 for (i = 0;i < texturenumsurfaces;i++)
11529 surface = texturesurfacelist[i];
11530 if (surface != firstsurface + i)
11532 surfacefirstvertex = surface->num_firstvertex;
11533 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11534 surfacenumvertices = surface->num_vertices;
11535 surfacenumtriangles = surface->num_triangles;
11536 if (firstvertex > surfacefirstvertex)
11537 firstvertex = surfacefirstvertex;
11538 if (endvertex < surfaceendvertex)
11539 endvertex = surfaceendvertex;
11540 batchnumvertices += surfacenumvertices;
11541 batchnumtriangles += surfacenumtriangles;
11544 // we now know the vertex range used, and if there are any gaps in it
11545 rsurface.batchfirstvertex = firstvertex;
11546 rsurface.batchnumvertices = endvertex - firstvertex;
11547 rsurface.batchfirsttriangle = firsttriangle;
11548 rsurface.batchnumtriangles = batchnumtriangles;
11550 // this variable holds flags for which properties have been updated that
11551 // may require regenerating vertexmesh array...
11554 // check if any dynamic vertex processing must occur
11555 dynamicvertex = false;
11557 // if there is a chance of animated vertex colors, it's a dynamic batch
11558 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11560 dynamicvertex = true;
11561 batchneed |= BATCHNEED_NOGAPS;
11562 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
11565 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11567 switch (deform->deform)
11570 case Q3DEFORM_PROJECTIONSHADOW:
11571 case Q3DEFORM_TEXT0:
11572 case Q3DEFORM_TEXT1:
11573 case Q3DEFORM_TEXT2:
11574 case Q3DEFORM_TEXT3:
11575 case Q3DEFORM_TEXT4:
11576 case Q3DEFORM_TEXT5:
11577 case Q3DEFORM_TEXT6:
11578 case Q3DEFORM_TEXT7:
11579 case Q3DEFORM_NONE:
11581 case Q3DEFORM_AUTOSPRITE:
11582 dynamicvertex = true;
11583 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11584 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11586 case Q3DEFORM_AUTOSPRITE2:
11587 dynamicvertex = true;
11588 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11589 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11591 case Q3DEFORM_NORMAL:
11592 dynamicvertex = true;
11593 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11594 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11596 case Q3DEFORM_WAVE:
11597 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11598 break; // if wavefunc is a nop, ignore this transform
11599 dynamicvertex = true;
11600 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11601 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11603 case Q3DEFORM_BULGE:
11604 dynamicvertex = true;
11605 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11606 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11608 case Q3DEFORM_MOVE:
11609 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11610 break; // if wavefunc is a nop, ignore this transform
11611 dynamicvertex = true;
11612 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11613 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
11617 switch(rsurface.texture->tcgen.tcgen)
11620 case Q3TCGEN_TEXTURE:
11622 case Q3TCGEN_LIGHTMAP:
11623 dynamicvertex = true;
11624 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11625 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11627 case Q3TCGEN_VECTOR:
11628 dynamicvertex = true;
11629 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11630 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11632 case Q3TCGEN_ENVIRONMENT:
11633 dynamicvertex = true;
11634 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11635 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11638 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11640 dynamicvertex = true;
11641 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11642 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11645 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11647 dynamicvertex = true;
11648 batchneed |= BATCHNEED_NOGAPS;
11649 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11652 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11654 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11655 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
11656 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
11657 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
11658 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11659 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11660 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11663 // when the model data has no vertex buffer (dynamic mesh), we need to
11665 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
11666 batchneed |= BATCHNEED_NOGAPS;
11668 // if needsupdate, we have to do a dynamic vertex batch for sure
11669 if (needsupdate & batchneed)
11670 dynamicvertex = true;
11672 // see if we need to build vertexmesh from arrays
11673 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11674 dynamicvertex = true;
11676 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11677 // also some drivers strongly dislike firstvertex
11678 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11679 dynamicvertex = true;
11681 rsurface.batchvertex3f = rsurface.modelvertex3f;
11682 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11683 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11684 rsurface.batchsvector3f = rsurface.modelsvector3f;
11685 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11686 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11687 rsurface.batchtvector3f = rsurface.modeltvector3f;
11688 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11689 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11690 rsurface.batchnormal3f = rsurface.modelnormal3f;
11691 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11692 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11693 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11694 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
11695 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11696 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11697 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
11698 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
11699 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11700 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11701 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11702 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
11703 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11704 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11705 rsurface.batchelement3i = rsurface.modelelement3i;
11706 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11707 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11708 rsurface.batchelement3s = rsurface.modelelement3s;
11709 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11710 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11712 // if any dynamic vertex processing has to occur in software, we copy the
11713 // entire surface list together before processing to rebase the vertices
11714 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11716 // if any gaps exist and we do not have a static vertex buffer, we have to
11717 // copy the surface list together to avoid wasting upload bandwidth on the
11718 // vertices in the gaps.
11720 // if gaps exist and we have a static vertex buffer, we still have to
11721 // combine the index buffer ranges into one dynamic index buffer.
11723 // in all cases we end up with data that can be drawn in one call.
11725 if (!dynamicvertex)
11727 // static vertex data, just set pointers...
11728 rsurface.batchgeneratedvertex = false;
11729 // if there are gaps, we want to build a combined index buffer,
11730 // otherwise use the original static buffer with an appropriate offset
11733 // build a new triangle elements array for this batch
11734 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11735 rsurface.batchfirsttriangle = 0;
11737 for (i = 0;i < texturenumsurfaces;i++)
11739 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11740 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11741 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11742 numtriangles += surfacenumtriangles;
11744 rsurface.batchelement3i_indexbuffer = NULL;
11745 rsurface.batchelement3i_bufferoffset = 0;
11746 rsurface.batchelement3s = NULL;
11747 rsurface.batchelement3s_indexbuffer = NULL;
11748 rsurface.batchelement3s_bufferoffset = 0;
11749 if (endvertex <= 65536)
11751 // make a 16bit (unsigned short) index array if possible
11752 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11753 for (i = 0;i < numtriangles*3;i++)
11754 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11760 // something needs software processing, do it for real...
11761 // we only directly handle separate array data in this case and then
11762 // generate interleaved data if needed...
11763 rsurface.batchgeneratedvertex = true;
11765 // now copy the vertex data into a combined array and make an index array
11766 // (this is what Quake3 does all the time)
11767 //if (gaps || rsurface.batchfirstvertex)
11769 rsurface.batchvertex3fbuffer = NULL;
11770 rsurface.batchvertexmesh = NULL;
11771 rsurface.batchvertexmeshbuffer = NULL;
11772 rsurface.batchvertex3f = NULL;
11773 rsurface.batchvertex3f_vertexbuffer = NULL;
11774 rsurface.batchvertex3f_bufferoffset = 0;
11775 rsurface.batchsvector3f = NULL;
11776 rsurface.batchsvector3f_vertexbuffer = NULL;
11777 rsurface.batchsvector3f_bufferoffset = 0;
11778 rsurface.batchtvector3f = NULL;
11779 rsurface.batchtvector3f_vertexbuffer = NULL;
11780 rsurface.batchtvector3f_bufferoffset = 0;
11781 rsurface.batchnormal3f = NULL;
11782 rsurface.batchnormal3f_vertexbuffer = NULL;
11783 rsurface.batchnormal3f_bufferoffset = 0;
11784 rsurface.batchlightmapcolor4f = NULL;
11785 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11786 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11787 rsurface.batchtexcoordtexture2f = NULL;
11788 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11789 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11790 rsurface.batchtexcoordlightmap2f = NULL;
11791 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11792 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11793 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11794 rsurface.batchelement3i_indexbuffer = NULL;
11795 rsurface.batchelement3i_bufferoffset = 0;
11796 rsurface.batchelement3s = NULL;
11797 rsurface.batchelement3s_indexbuffer = NULL;
11798 rsurface.batchelement3s_bufferoffset = 0;
11799 // we'll only be setting up certain arrays as needed
11800 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11801 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
11802 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11803 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11804 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11805 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11806 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11808 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11809 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11811 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11812 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11813 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11814 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11815 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11816 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11819 for (i = 0;i < texturenumsurfaces;i++)
11821 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11822 surfacenumvertices = texturesurfacelist[i]->num_vertices;
11823 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11824 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11825 // copy only the data requested
11826 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11827 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11828 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11830 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11831 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11832 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11833 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11834 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11836 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11837 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11839 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11840 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11841 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11842 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11843 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11844 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11846 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11847 numvertices += surfacenumvertices;
11848 numtriangles += surfacenumtriangles;
11851 // generate a 16bit index array as well if possible
11852 // (in general, dynamic batches fit)
11853 if (numvertices <= 65536)
11855 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11856 for (i = 0;i < numtriangles*3;i++)
11857 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11860 // since we've copied everything, the batch now starts at 0
11861 rsurface.batchfirstvertex = 0;
11862 rsurface.batchnumvertices = batchnumvertices;
11863 rsurface.batchfirsttriangle = 0;
11864 rsurface.batchnumtriangles = batchnumtriangles;
11867 // q1bsp surfaces rendered in vertex color mode have to have colors
11868 // calculated based on lightstyles
11869 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11871 // generate color arrays for the surfaces in this list
11875 const int *offsets;
11876 const unsigned char *lm;
11877 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11878 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11879 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11881 for (i = 0;i < texturenumsurfaces;i++)
11883 surface = texturesurfacelist[i];
11884 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11885 surfacenumvertices = surface->num_vertices;
11886 if (surface->lightmapinfo->samples)
11888 for (j = 0;j < surfacenumvertices;j++)
11890 lm = surface->lightmapinfo->samples + offsets[j];
11891 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11892 VectorScale(lm, scale, c);
11893 if (surface->lightmapinfo->styles[1] != 255)
11895 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11897 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11898 VectorMA(c, scale, lm, c);
11899 if (surface->lightmapinfo->styles[2] != 255)
11902 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11903 VectorMA(c, scale, lm, c);
11904 if (surface->lightmapinfo->styles[3] != 255)
11907 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11908 VectorMA(c, scale, lm, c);
11915 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, min(c[0], 255) * (1.0f / 255.0f), min(c[1], 255) * (1.0f / 255.0f), min(c[2], 255) * (1.0f / 255.0f), 1);
11921 for (j = 0;j < surfacenumvertices;j++)
11923 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11930 // if vertices are deformed (sprite flares and things in maps, possibly
11931 // water waves, bulges and other deformations), modify the copied vertices
11933 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11935 switch (deform->deform)
11938 case Q3DEFORM_PROJECTIONSHADOW:
11939 case Q3DEFORM_TEXT0:
11940 case Q3DEFORM_TEXT1:
11941 case Q3DEFORM_TEXT2:
11942 case Q3DEFORM_TEXT3:
11943 case Q3DEFORM_TEXT4:
11944 case Q3DEFORM_TEXT5:
11945 case Q3DEFORM_TEXT6:
11946 case Q3DEFORM_TEXT7:
11947 case Q3DEFORM_NONE:
11949 case Q3DEFORM_AUTOSPRITE:
11950 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11951 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11952 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11953 VectorNormalize(newforward);
11954 VectorNormalize(newright);
11955 VectorNormalize(newup);
11956 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11957 // rsurface.batchvertex3f_vertexbuffer = NULL;
11958 // rsurface.batchvertex3f_bufferoffset = 0;
11959 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
11960 // rsurface.batchsvector3f_vertexbuffer = NULL;
11961 // rsurface.batchsvector3f_bufferoffset = 0;
11962 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
11963 // rsurface.batchtvector3f_vertexbuffer = NULL;
11964 // rsurface.batchtvector3f_bufferoffset = 0;
11965 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11966 // rsurface.batchnormal3f_vertexbuffer = NULL;
11967 // rsurface.batchnormal3f_bufferoffset = 0;
11968 // a single autosprite surface can contain multiple sprites...
11969 for (j = 0;j < batchnumvertices - 3;j += 4)
11971 VectorClear(center);
11972 for (i = 0;i < 4;i++)
11973 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11974 VectorScale(center, 0.25f, center);
11975 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11976 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11977 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11978 for (i = 0;i < 4;i++)
11980 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11981 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
11984 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11985 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11986 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
11988 case Q3DEFORM_AUTOSPRITE2:
11989 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11990 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11991 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11992 VectorNormalize(newforward);
11993 VectorNormalize(newright);
11994 VectorNormalize(newup);
11995 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11996 // rsurface.batchvertex3f_vertexbuffer = NULL;
11997 // rsurface.batchvertex3f_bufferoffset = 0;
11999 const float *v1, *v2;
12009 memset(shortest, 0, sizeof(shortest));
12010 // a single autosprite surface can contain multiple sprites...
12011 for (j = 0;j < batchnumvertices - 3;j += 4)
12013 VectorClear(center);
12014 for (i = 0;i < 4;i++)
12015 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
12016 VectorScale(center, 0.25f, center);
12017 // find the two shortest edges, then use them to define the
12018 // axis vectors for rotating around the central axis
12019 for (i = 0;i < 6;i++)
12021 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
12022 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
12023 l = VectorDistance2(v1, v2);
12024 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
12025 if (v1[2] != v2[2])
12026 l += (1.0f / 1024.0f);
12027 if (shortest[0].length2 > l || i == 0)
12029 shortest[1] = shortest[0];
12030 shortest[0].length2 = l;
12031 shortest[0].v1 = v1;
12032 shortest[0].v2 = v2;
12034 else if (shortest[1].length2 > l || i == 1)
12036 shortest[1].length2 = l;
12037 shortest[1].v1 = v1;
12038 shortest[1].v2 = v2;
12041 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
12042 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
12043 // this calculates the right vector from the shortest edge
12044 // and the up vector from the edge midpoints
12045 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
12046 VectorNormalize(right);
12047 VectorSubtract(end, start, up);
12048 VectorNormalize(up);
12049 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
12050 VectorSubtract(rsurface.localvieworigin, center, forward);
12051 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
12052 VectorNegate(forward, forward);
12053 VectorReflect(forward, 0, up, forward);
12054 VectorNormalize(forward);
12055 CrossProduct(up, forward, newright);
12056 VectorNormalize(newright);
12057 // rotate the quad around the up axis vector, this is made
12058 // especially easy by the fact we know the quad is flat,
12059 // so we only have to subtract the center position and
12060 // measure distance along the right vector, and then
12061 // multiply that by the newright vector and add back the
12063 // we also need to subtract the old position to undo the
12064 // displacement from the center, which we do with a
12065 // DotProduct, the subtraction/addition of center is also
12066 // optimized into DotProducts here
12067 l = DotProduct(right, center);
12068 for (i = 0;i < 4;i++)
12070 v1 = rsurface.batchvertex3f + 3*(j+i);
12071 f = DotProduct(right, v1) - l;
12072 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
12076 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
12078 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12079 // rsurface.batchnormal3f_vertexbuffer = NULL;
12080 // rsurface.batchnormal3f_bufferoffset = 0;
12081 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12083 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12085 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12086 // rsurface.batchsvector3f_vertexbuffer = NULL;
12087 // rsurface.batchsvector3f_bufferoffset = 0;
12088 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12089 // rsurface.batchtvector3f_vertexbuffer = NULL;
12090 // rsurface.batchtvector3f_bufferoffset = 0;
12091 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
12094 case Q3DEFORM_NORMAL:
12095 // deform the normals to make reflections wavey
12096 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
12097 rsurface.batchnormal3f_vertexbuffer = NULL;
12098 rsurface.batchnormal3f_bufferoffset = 0;
12099 for (j = 0;j < batchnumvertices;j++)
12102 float *normal = rsurface.batchnormal3f + 3*j;
12103 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
12104 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
12105 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]);
12106 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]);
12107 VectorNormalize(normal);
12109 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12111 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12112 // rsurface.batchsvector3f_vertexbuffer = NULL;
12113 // rsurface.batchsvector3f_bufferoffset = 0;
12114 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12115 // rsurface.batchtvector3f_vertexbuffer = NULL;
12116 // rsurface.batchtvector3f_bufferoffset = 0;
12117 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
12120 case Q3DEFORM_WAVE:
12121 // deform vertex array to make wavey water and flags and such
12122 waveparms[0] = deform->waveparms[0];
12123 waveparms[1] = deform->waveparms[1];
12124 waveparms[2] = deform->waveparms[2];
12125 waveparms[3] = deform->waveparms[3];
12126 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
12127 break; // if wavefunc is a nop, don't make a dynamic vertex array
12128 // this is how a divisor of vertex influence on deformation
12129 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
12130 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
12131 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
12132 // rsurface.batchvertex3f_vertexbuffer = NULL;
12133 // rsurface.batchvertex3f_bufferoffset = 0;
12134 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
12135 // rsurface.batchnormal3f_vertexbuffer = NULL;
12136 // rsurface.batchnormal3f_bufferoffset = 0;
12137 for (j = 0;j < batchnumvertices;j++)
12139 // if the wavefunc depends on time, evaluate it per-vertex
12142 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
12143 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
12145 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
12147 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12148 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12149 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12151 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12152 // rsurface.batchsvector3f_vertexbuffer = NULL;
12153 // rsurface.batchsvector3f_bufferoffset = 0;
12154 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12155 // rsurface.batchtvector3f_vertexbuffer = NULL;
12156 // rsurface.batchtvector3f_bufferoffset = 0;
12157 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
12160 case Q3DEFORM_BULGE:
12161 // deform vertex array to make the surface have moving bulges
12162 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
12163 // rsurface.batchvertex3f_vertexbuffer = NULL;
12164 // rsurface.batchvertex3f_bufferoffset = 0;
12165 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
12166 // rsurface.batchnormal3f_vertexbuffer = NULL;
12167 // rsurface.batchnormal3f_bufferoffset = 0;
12168 for (j = 0;j < batchnumvertices;j++)
12170 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
12171 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
12173 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12174 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12175 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12177 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12178 // rsurface.batchsvector3f_vertexbuffer = NULL;
12179 // rsurface.batchsvector3f_bufferoffset = 0;
12180 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12181 // rsurface.batchtvector3f_vertexbuffer = NULL;
12182 // rsurface.batchtvector3f_bufferoffset = 0;
12183 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
12186 case Q3DEFORM_MOVE:
12187 // deform vertex array
12188 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
12189 break; // if wavefunc is a nop, don't make a dynamic vertex array
12190 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
12191 VectorScale(deform->parms, scale, waveparms);
12192 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
12193 // rsurface.batchvertex3f_vertexbuffer = NULL;
12194 // rsurface.batchvertex3f_bufferoffset = 0;
12195 for (j = 0;j < batchnumvertices;j++)
12196 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
12201 // generate texcoords based on the chosen texcoord source
12202 switch(rsurface.texture->tcgen.tcgen)
12205 case Q3TCGEN_TEXTURE:
12207 case Q3TCGEN_LIGHTMAP:
12208 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12209 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12210 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12211 if (rsurface.batchtexcoordlightmap2f)
12212 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
12214 case Q3TCGEN_VECTOR:
12215 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12216 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12217 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12218 for (j = 0;j < batchnumvertices;j++)
12220 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
12221 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
12224 case Q3TCGEN_ENVIRONMENT:
12225 // make environment reflections using a spheremap
12226 rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12227 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12228 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12229 for (j = 0;j < batchnumvertices;j++)
12231 // identical to Q3A's method, but executed in worldspace so
12232 // carried models can be shiny too
12234 float viewer[3], d, reflected[3], worldreflected[3];
12236 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
12237 // VectorNormalize(viewer);
12239 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
12241 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
12242 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
12243 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
12244 // note: this is proportinal to viewer, so we can normalize later
12246 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
12247 VectorNormalize(worldreflected);
12249 // note: this sphere map only uses world x and z!
12250 // so positive and negative y will LOOK THE SAME.
12251 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
12252 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
12256 // the only tcmod that needs software vertex processing is turbulent, so
12257 // check for it here and apply the changes if needed
12258 // and we only support that as the first one
12259 // (handling a mixture of turbulent and other tcmods would be problematic
12260 // without punting it entirely to a software path)
12261 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
12263 amplitude = rsurface.texture->tcmods[0].parms[1];
12264 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
12265 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12266 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12267 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12268 for (j = 0;j < batchnumvertices;j++)
12270 rsurface.batchtexcoordtexture2f[j*2+0] += amplitude * sin(((rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12271 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12275 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
12277 // convert the modified arrays to vertex structs
12278 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
12279 // rsurface.batchvertexmeshbuffer = NULL;
12280 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
12281 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12282 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
12283 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
12284 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12285 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
12286 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
12288 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12290 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
12291 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
12294 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
12295 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12296 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
12297 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
12298 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12299 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
12300 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
12301 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12302 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
12306 void RSurf_DrawBatch(void)
12308 // sometimes a zero triangle surface (usually a degenerate patch) makes it
12309 // through the pipeline, killing it earlier in the pipeline would have
12310 // per-surface overhead rather than per-batch overhead, so it's best to
12311 // reject it here, before it hits glDraw.
12312 if (rsurface.batchnumtriangles == 0)
12315 // batch debugging code
12316 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
12322 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
12323 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
12326 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
12328 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
12330 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
12331 Sys_Error("RSurf_DrawBatch: index %i uses different texture (%s) than surface %i which it belongs to (which uses %s)\n", c, rsurface.texture->name, j, rsurface.modelsurfaces[j].texture->name);
12338 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);
12341 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
12343 // pick the closest matching water plane
12344 int planeindex, vertexindex, bestplaneindex = -1;
12348 r_waterstate_waterplane_t *p;
12349 qboolean prepared = false;
12351 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
12353 if(p->camera_entity != rsurface.texture->camera_entity)
12358 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12360 if(rsurface.batchnumvertices == 0)
12363 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
12365 Matrix4x4_Transform(&rsurface.matrix, v, vert);
12366 d += fabs(PlaneDiff(vert, &p->plane));
12368 if (bestd > d || bestplaneindex < 0)
12371 bestplaneindex = planeindex;
12374 return bestplaneindex;
12375 // NOTE: this MAY return a totally unrelated water plane; we can ignore
12376 // this situation though, as it might be better to render single larger
12377 // batches with useless stuff (backface culled for example) than to
12378 // render multiple smaller batches
12381 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
12384 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12385 rsurface.passcolor4f_vertexbuffer = 0;
12386 rsurface.passcolor4f_bufferoffset = 0;
12387 for (i = 0;i < rsurface.batchnumvertices;i++)
12388 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
12391 static void RSurf_DrawBatch_GL11_ApplyFog(void)
12398 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12399 rsurface.passcolor4f_vertexbuffer = 0;
12400 rsurface.passcolor4f_bufferoffset = 0;
12401 if (rsurface.passcolor4f)
12403 // generate color arrays
12404 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
12406 f = RSurf_FogVertex(v);
12415 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
12417 f = RSurf_FogVertex(v);
12426 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
12433 if (!rsurface.passcolor4f)
12435 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12436 rsurface.passcolor4f_vertexbuffer = 0;
12437 rsurface.passcolor4f_bufferoffset = 0;
12438 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
12440 f = RSurf_FogVertex(v);
12441 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
12442 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
12443 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
12448 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
12453 if (!rsurface.passcolor4f)
12455 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
12456 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12457 rsurface.passcolor4f_vertexbuffer = 0;
12458 rsurface.passcolor4f_bufferoffset = 0;
12459 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12468 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12473 if (!rsurface.passcolor4f)
12475 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12476 rsurface.passcolor4f_vertexbuffer = 0;
12477 rsurface.passcolor4f_bufferoffset = 0;
12478 for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12480 c2[0] = c[0] + r_refdef.scene.ambient;
12481 c2[1] = c[1] + r_refdef.scene.ambient;
12482 c2[2] = c[2] + r_refdef.scene.ambient;
12487 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12490 rsurface.passcolor4f = NULL;
12491 rsurface.passcolor4f_vertexbuffer = 0;
12492 rsurface.passcolor4f_bufferoffset = 0;
12493 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12494 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12495 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12496 GL_Color(r, g, b, a);
12497 R_Mesh_TexBind(0, rsurface.lightmaptexture);
12501 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12503 // TODO: optimize applyfog && applycolor case
12504 // just apply fog if necessary, and tint the fog color array if necessary
12505 rsurface.passcolor4f = NULL;
12506 rsurface.passcolor4f_vertexbuffer = 0;
12507 rsurface.passcolor4f_bufferoffset = 0;
12508 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12509 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12510 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12511 GL_Color(r, g, b, a);
12515 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12518 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12519 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12520 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12521 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12522 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12523 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12524 GL_Color(r, g, b, a);
12528 static void RSurf_DrawBatch_GL11_ClampColor(void)
12533 if (!rsurface.passcolor4f)
12535 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12537 c2[0] = bound(0.0f, c1[0], 1.0f);
12538 c2[1] = bound(0.0f, c1[1], 1.0f);
12539 c2[2] = bound(0.0f, c1[2], 1.0f);
12540 c2[3] = bound(0.0f, c1[3], 1.0f);
12544 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
12554 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12555 rsurface.passcolor4f_vertexbuffer = 0;
12556 rsurface.passcolor4f_bufferoffset = 0;
12557 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
12559 f = -DotProduct(r_refdef.view.forward, n);
12561 f = f * 0.85 + 0.15; // work around so stuff won't get black
12562 f *= r_refdef.lightmapintensity;
12563 Vector4Set(c, f, f, f, 1);
12567 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12569 RSurf_DrawBatch_GL11_ApplyFakeLight();
12570 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12571 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12572 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12573 GL_Color(r, g, b, a);
12577 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12585 vec3_t ambientcolor;
12586 vec3_t diffusecolor;
12590 VectorCopy(rsurface.modellight_lightdir, lightdir);
12591 f = 0.5f * r_refdef.lightmapintensity;
12592 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12593 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12594 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12595 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12596 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12597 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12599 if (VectorLength2(diffusecolor) > 0)
12601 // q3-style directional shading
12602 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12603 rsurface.passcolor4f_vertexbuffer = 0;
12604 rsurface.passcolor4f_bufferoffset = 0;
12605 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
12607 if ((f = DotProduct(n, lightdir)) > 0)
12608 VectorMA(ambientcolor, f, diffusecolor, c);
12610 VectorCopy(ambientcolor, c);
12617 *applycolor = false;
12621 *r = ambientcolor[0];
12622 *g = ambientcolor[1];
12623 *b = ambientcolor[2];
12624 rsurface.passcolor4f = NULL;
12625 rsurface.passcolor4f_vertexbuffer = 0;
12626 rsurface.passcolor4f_bufferoffset = 0;
12630 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12632 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12633 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12634 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12635 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12636 GL_Color(r, g, b, a);
12640 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12646 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12648 f = 1 - RSurf_FogVertex(v);
12656 void RSurf_SetupDepthAndCulling(void)
12658 // submodels are biased to avoid z-fighting with world surfaces that they
12659 // may be exactly overlapping (avoids z-fighting artifacts on certain
12660 // doors and things in Quake maps)
12661 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12662 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12663 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12664 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12667 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12669 // transparent sky would be ridiculous
12670 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12672 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12673 skyrenderlater = true;
12674 RSurf_SetupDepthAndCulling();
12675 GL_DepthMask(true);
12676 // LordHavoc: HalfLife maps have freaky skypolys so don't use
12677 // skymasking on them, and Quake3 never did sky masking (unlike
12678 // software Quake and software Quake2), so disable the sky masking
12679 // in Quake3 maps as it causes problems with q3map2 sky tricks,
12680 // and skymasking also looks very bad when noclipping outside the
12681 // level, so don't use it then either.
12682 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12684 R_Mesh_ResetTextureState();
12685 if (skyrendermasked)
12687 R_SetupShader_DepthOrShadow();
12688 // depth-only (masking)
12689 GL_ColorMask(0,0,0,0);
12690 // just to make sure that braindead drivers don't draw
12691 // anything despite that colormask...
12692 GL_BlendFunc(GL_ZERO, GL_ONE);
12693 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12694 if (rsurface.batchvertex3fbuffer)
12695 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12697 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12701 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12703 GL_BlendFunc(GL_ONE, GL_ZERO);
12704 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12705 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12706 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12709 if (skyrendermasked)
12710 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12712 R_Mesh_ResetTextureState();
12713 GL_Color(1, 1, 1, 1);
12716 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12717 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12718 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12720 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12724 // render screenspace normalmap to texture
12725 GL_DepthMask(true);
12726 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12731 // bind lightmap texture
12733 // water/refraction/reflection/camera surfaces have to be handled specially
12734 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
12736 int start, end, startplaneindex;
12737 for (start = 0;start < texturenumsurfaces;start = end)
12739 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12740 if(startplaneindex < 0)
12742 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
12743 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
12747 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12749 // now that we have a batch using the same planeindex, render it
12750 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
12752 // render water or distortion background
12753 GL_DepthMask(true);
12754 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));
12756 // blend surface on top
12757 GL_DepthMask(false);
12758 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12761 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
12763 // render surface with reflection texture as input
12764 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12765 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));
12772 // render surface batch normally
12773 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12774 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12778 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12780 // OpenGL 1.3 path - anything not completely ancient
12781 qboolean applycolor;
12784 const texturelayer_t *layer;
12785 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);
12786 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12788 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12791 int layertexrgbscale;
12792 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12794 if (layerindex == 0)
12795 GL_AlphaTest(true);
12798 GL_AlphaTest(false);
12799 GL_DepthFunc(GL_EQUAL);
12802 GL_DepthMask(layer->depthmask && writedepth);
12803 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12804 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12806 layertexrgbscale = 4;
12807 VectorScale(layer->color, 0.25f, layercolor);
12809 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12811 layertexrgbscale = 2;
12812 VectorScale(layer->color, 0.5f, layercolor);
12816 layertexrgbscale = 1;
12817 VectorScale(layer->color, 1.0f, layercolor);
12819 layercolor[3] = layer->color[3];
12820 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12821 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12822 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12823 switch (layer->type)
12825 case TEXTURELAYERTYPE_LITTEXTURE:
12826 // single-pass lightmapped texture with 2x rgbscale
12827 R_Mesh_TexBind(0, r_texture_white);
12828 R_Mesh_TexMatrix(0, NULL);
12829 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12830 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12831 R_Mesh_TexBind(1, layer->texture);
12832 R_Mesh_TexMatrix(1, &layer->texmatrix);
12833 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12834 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12835 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12836 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12837 else if (FAKELIGHT_ENABLED)
12838 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12839 else if (rsurface.uselightmaptexture)
12840 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12842 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12844 case TEXTURELAYERTYPE_TEXTURE:
12845 // singletexture unlit texture with transparency support
12846 R_Mesh_TexBind(0, layer->texture);
12847 R_Mesh_TexMatrix(0, &layer->texmatrix);
12848 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12849 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12850 R_Mesh_TexBind(1, 0);
12851 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12852 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12854 case TEXTURELAYERTYPE_FOG:
12855 // singletexture fogging
12856 if (layer->texture)
12858 R_Mesh_TexBind(0, layer->texture);
12859 R_Mesh_TexMatrix(0, &layer->texmatrix);
12860 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12861 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12865 R_Mesh_TexBind(0, 0);
12866 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12868 R_Mesh_TexBind(1, 0);
12869 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12870 // generate a color array for the fog pass
12871 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12872 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12876 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12879 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12881 GL_DepthFunc(GL_LEQUAL);
12882 GL_AlphaTest(false);
12886 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12888 // OpenGL 1.1 - crusty old voodoo path
12891 const texturelayer_t *layer;
12892 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);
12893 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12895 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12897 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12899 if (layerindex == 0)
12900 GL_AlphaTest(true);
12903 GL_AlphaTest(false);
12904 GL_DepthFunc(GL_EQUAL);
12907 GL_DepthMask(layer->depthmask && writedepth);
12908 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12909 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12910 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12911 switch (layer->type)
12913 case TEXTURELAYERTYPE_LITTEXTURE:
12914 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12916 // two-pass lit texture with 2x rgbscale
12917 // first the lightmap pass
12918 R_Mesh_TexBind(0, r_texture_white);
12919 R_Mesh_TexMatrix(0, NULL);
12920 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12921 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12922 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12923 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12924 else if (FAKELIGHT_ENABLED)
12925 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12926 else if (rsurface.uselightmaptexture)
12927 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12929 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12930 // then apply the texture to it
12931 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12932 R_Mesh_TexBind(0, layer->texture);
12933 R_Mesh_TexMatrix(0, &layer->texmatrix);
12934 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12935 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12936 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);
12940 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12941 R_Mesh_TexBind(0, layer->texture);
12942 R_Mesh_TexMatrix(0, &layer->texmatrix);
12943 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12944 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12945 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12946 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);
12948 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);
12951 case TEXTURELAYERTYPE_TEXTURE:
12952 // singletexture unlit texture with transparency support
12953 R_Mesh_TexBind(0, layer->texture);
12954 R_Mesh_TexMatrix(0, &layer->texmatrix);
12955 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12956 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12957 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);
12959 case TEXTURELAYERTYPE_FOG:
12960 // singletexture fogging
12961 if (layer->texture)
12963 R_Mesh_TexBind(0, layer->texture);
12964 R_Mesh_TexMatrix(0, &layer->texmatrix);
12965 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12966 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12970 R_Mesh_TexBind(0, 0);
12971 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12973 // generate a color array for the fog pass
12974 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12975 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12979 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12982 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12984 GL_DepthFunc(GL_LEQUAL);
12985 GL_AlphaTest(false);
12989 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12993 r_vertexgeneric_t *batchvertex;
12996 GL_AlphaTest(false);
12997 // R_Mesh_ResetTextureState();
12998 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13000 if(rsurface.texture && rsurface.texture->currentskinframe)
13002 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
13003 c[3] *= rsurface.texture->currentalpha;
13013 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
13015 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
13016 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
13017 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
13020 // brighten it up (as texture value 127 means "unlit")
13021 c[0] *= 2 * r_refdef.view.colorscale;
13022 c[1] *= 2 * r_refdef.view.colorscale;
13023 c[2] *= 2 * r_refdef.view.colorscale;
13025 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
13026 c[3] *= r_wateralpha.value;
13028 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
13030 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13031 GL_DepthMask(false);
13033 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
13035 GL_BlendFunc(GL_ONE, GL_ONE);
13036 GL_DepthMask(false);
13038 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
13040 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
13041 GL_DepthMask(false);
13043 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
13045 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
13046 GL_DepthMask(false);
13050 GL_BlendFunc(GL_ONE, GL_ZERO);
13051 GL_DepthMask(writedepth);
13054 if (r_showsurfaces.integer == 3)
13056 rsurface.passcolor4f = NULL;
13058 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
13060 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13062 rsurface.passcolor4f = NULL;
13063 rsurface.passcolor4f_vertexbuffer = 0;
13064 rsurface.passcolor4f_bufferoffset = 0;
13066 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
13068 qboolean applycolor = true;
13071 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13073 r_refdef.lightmapintensity = 1;
13074 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
13075 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
13077 else if (FAKELIGHT_ENABLED)
13079 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13081 r_refdef.lightmapintensity = r_fakelight_intensity.value;
13082 RSurf_DrawBatch_GL11_ApplyFakeLight();
13083 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
13087 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13089 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
13090 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
13091 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
13094 if(!rsurface.passcolor4f)
13095 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
13097 RSurf_DrawBatch_GL11_ApplyAmbient();
13098 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
13099 if(r_refdef.fogenabled)
13100 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
13101 RSurf_DrawBatch_GL11_ClampColor();
13103 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
13104 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13107 else if (!r_refdef.view.showdebug)
13109 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13110 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
13111 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
13113 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13114 Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
13116 R_Mesh_PrepareVertices_Generic_Unlock();
13119 else if (r_showsurfaces.integer == 4)
13121 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13122 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
13123 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
13125 unsigned char c = vi << 3;
13126 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13127 Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
13129 R_Mesh_PrepareVertices_Generic_Unlock();
13132 else if (r_showsurfaces.integer == 2)
13135 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13136 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
13137 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
13139 unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
13140 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
13141 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
13142 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
13143 Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
13144 Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
13145 Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
13147 R_Mesh_PrepareVertices_Generic_Unlock();
13148 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
13152 int texturesurfaceindex;
13154 const msurface_t *surface;
13155 unsigned char surfacecolor4ub[4];
13156 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13157 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
13159 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
13161 surface = texturesurfacelist[texturesurfaceindex];
13162 k = (int)(((size_t)surface) / sizeof(msurface_t));
13163 Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
13164 for (j = 0;j < surface->num_vertices;j++)
13166 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13167 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
13171 R_Mesh_PrepareVertices_Generic_Unlock();
13176 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13179 RSurf_SetupDepthAndCulling();
13180 if (r_showsurfaces.integer)
13182 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13185 switch (vid.renderpath)
13187 case RENDERPATH_GL20:
13188 case RENDERPATH_CGGL:
13189 case RENDERPATH_D3D9:
13190 case RENDERPATH_D3D10:
13191 case RENDERPATH_D3D11:
13192 case RENDERPATH_SOFT:
13193 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13195 case RENDERPATH_GL13:
13196 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13198 case RENDERPATH_GL11:
13199 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13205 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13208 RSurf_SetupDepthAndCulling();
13209 if (r_showsurfaces.integer)
13211 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13214 switch (vid.renderpath)
13216 case RENDERPATH_GL20:
13217 case RENDERPATH_CGGL:
13218 case RENDERPATH_D3D9:
13219 case RENDERPATH_D3D10:
13220 case RENDERPATH_D3D11:
13221 case RENDERPATH_SOFT:
13222 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13224 case RENDERPATH_GL13:
13225 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13227 case RENDERPATH_GL11:
13228 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13234 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13237 int texturenumsurfaces, endsurface;
13238 texture_t *texture;
13239 const msurface_t *surface;
13240 #define MAXBATCH_TRANSPARENTSURFACES 256
13241 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
13243 // if the model is static it doesn't matter what value we give for
13244 // wantnormals and wanttangents, so this logic uses only rules applicable
13245 // to a model, knowing that they are meaningless otherwise
13246 if (ent == r_refdef.scene.worldentity)
13247 RSurf_ActiveWorldEntity();
13248 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13249 RSurf_ActiveModelEntity(ent, false, false, false);
13252 switch (vid.renderpath)
13254 case RENDERPATH_GL20:
13255 case RENDERPATH_CGGL:
13256 case RENDERPATH_D3D9:
13257 case RENDERPATH_D3D10:
13258 case RENDERPATH_D3D11:
13259 case RENDERPATH_SOFT:
13260 RSurf_ActiveModelEntity(ent, true, true, false);
13262 case RENDERPATH_GL13:
13263 case RENDERPATH_GL11:
13264 RSurf_ActiveModelEntity(ent, true, false, false);
13269 if (r_transparentdepthmasking.integer)
13271 qboolean setup = false;
13272 for (i = 0;i < numsurfaces;i = j)
13275 surface = rsurface.modelsurfaces + surfacelist[i];
13276 texture = surface->texture;
13277 rsurface.texture = R_GetCurrentTexture(texture);
13278 rsurface.lightmaptexture = NULL;
13279 rsurface.deluxemaptexture = NULL;
13280 rsurface.uselightmaptexture = false;
13281 // scan ahead until we find a different texture
13282 endsurface = min(i + 1024, numsurfaces);
13283 texturenumsurfaces = 0;
13284 texturesurfacelist[texturenumsurfaces++] = surface;
13285 for (;j < endsurface;j++)
13287 surface = rsurface.modelsurfaces + surfacelist[j];
13288 if (texture != surface->texture)
13290 texturesurfacelist[texturenumsurfaces++] = surface;
13292 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
13294 // render the range of surfaces as depth
13298 GL_ColorMask(0,0,0,0);
13300 GL_DepthTest(true);
13301 GL_BlendFunc(GL_ONE, GL_ZERO);
13302 GL_DepthMask(true);
13303 GL_AlphaTest(false);
13304 // R_Mesh_ResetTextureState();
13305 R_SetupShader_DepthOrShadow();
13307 RSurf_SetupDepthAndCulling();
13308 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
13309 if (rsurface.batchvertex3fbuffer)
13310 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
13312 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
13316 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
13319 for (i = 0;i < numsurfaces;i = j)
13322 surface = rsurface.modelsurfaces + surfacelist[i];
13323 texture = surface->texture;
13324 rsurface.texture = R_GetCurrentTexture(texture);
13325 // scan ahead until we find a different texture
13326 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
13327 texturenumsurfaces = 0;
13328 texturesurfacelist[texturenumsurfaces++] = surface;
13329 if(FAKELIGHT_ENABLED)
13331 rsurface.lightmaptexture = NULL;
13332 rsurface.deluxemaptexture = NULL;
13333 rsurface.uselightmaptexture = false;
13334 for (;j < endsurface;j++)
13336 surface = rsurface.modelsurfaces + surfacelist[j];
13337 if (texture != surface->texture)
13339 texturesurfacelist[texturenumsurfaces++] = surface;
13344 rsurface.lightmaptexture = surface->lightmaptexture;
13345 rsurface.deluxemaptexture = surface->deluxemaptexture;
13346 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
13347 for (;j < endsurface;j++)
13349 surface = rsurface.modelsurfaces + surfacelist[j];
13350 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
13352 texturesurfacelist[texturenumsurfaces++] = surface;
13355 // render the range of surfaces
13356 if (ent == r_refdef.scene.worldentity)
13357 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13359 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13361 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13362 GL_AlphaTest(false);
13365 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
13367 // transparent surfaces get pushed off into the transparent queue
13368 int surfacelistindex;
13369 const msurface_t *surface;
13370 vec3_t tempcenter, center;
13371 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
13373 surface = texturesurfacelist[surfacelistindex];
13374 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
13375 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
13376 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
13377 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
13378 if (queueentity->transparent_offset) // transparent offset
13380 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
13381 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
13382 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
13384 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
13388 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
13390 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
13392 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
13394 RSurf_SetupDepthAndCulling();
13395 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
13396 if (rsurface.batchvertex3fbuffer)
13397 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
13399 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
13403 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
13405 const entity_render_t *queueentity = r_refdef.scene.worldentity;
13408 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13411 if (!rsurface.texture->currentnumlayers)
13413 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13414 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13416 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13418 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13419 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13420 else if (!rsurface.texture->currentnumlayers)
13422 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13424 // in the deferred case, transparent surfaces were queued during prepass
13425 if (!r_shadow_usingdeferredprepass)
13426 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13430 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13431 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13436 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13439 texture_t *texture;
13440 R_FrameData_SetMark();
13441 // break the surface list down into batches by texture and use of lightmapping
13442 for (i = 0;i < numsurfaces;i = j)
13445 // texture is the base texture pointer, rsurface.texture is the
13446 // current frame/skin the texture is directing us to use (for example
13447 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13448 // use skin 1 instead)
13449 texture = surfacelist[i]->texture;
13450 rsurface.texture = R_GetCurrentTexture(texture);
13451 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13453 // if this texture is not the kind we want, skip ahead to the next one
13454 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13458 if(FAKELIGHT_ENABLED || depthonly || prepass)
13460 rsurface.lightmaptexture = NULL;
13461 rsurface.deluxemaptexture = NULL;
13462 rsurface.uselightmaptexture = false;
13463 // simply scan ahead until we find a different texture or lightmap state
13464 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13469 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13470 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13471 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13472 // simply scan ahead until we find a different texture or lightmap state
13473 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13476 // render the range of surfaces
13477 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
13479 R_FrameData_ReturnToMark();
13482 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
13486 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13489 if (!rsurface.texture->currentnumlayers)
13491 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13492 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13494 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13496 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13497 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13498 else if (!rsurface.texture->currentnumlayers)
13500 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13502 // in the deferred case, transparent surfaces were queued during prepass
13503 if (!r_shadow_usingdeferredprepass)
13504 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13508 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13509 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13514 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13517 texture_t *texture;
13518 R_FrameData_SetMark();
13519 // break the surface list down into batches by texture and use of lightmapping
13520 for (i = 0;i < numsurfaces;i = j)
13523 // texture is the base texture pointer, rsurface.texture is the
13524 // current frame/skin the texture is directing us to use (for example
13525 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13526 // use skin 1 instead)
13527 texture = surfacelist[i]->texture;
13528 rsurface.texture = R_GetCurrentTexture(texture);
13529 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13531 // if this texture is not the kind we want, skip ahead to the next one
13532 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13536 if(FAKELIGHT_ENABLED || depthonly || prepass)
13538 rsurface.lightmaptexture = NULL;
13539 rsurface.deluxemaptexture = NULL;
13540 rsurface.uselightmaptexture = false;
13541 // simply scan ahead until we find a different texture or lightmap state
13542 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13547 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13548 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13549 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13550 // simply scan ahead until we find a different texture or lightmap state
13551 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13554 // render the range of surfaces
13555 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
13557 R_FrameData_ReturnToMark();
13560 float locboxvertex3f[6*4*3] =
13562 1,0,1, 1,0,0, 1,1,0, 1,1,1,
13563 0,1,1, 0,1,0, 0,0,0, 0,0,1,
13564 1,1,1, 1,1,0, 0,1,0, 0,1,1,
13565 0,0,1, 0,0,0, 1,0,0, 1,0,1,
13566 0,0,1, 1,0,1, 1,1,1, 0,1,1,
13567 1,0,0, 0,0,0, 0,1,0, 1,1,0
13570 unsigned short locboxelements[6*2*3] =
13575 12,13,14, 12,14,15,
13576 16,17,18, 16,18,19,
13580 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13583 cl_locnode_t *loc = (cl_locnode_t *)ent;
13585 float vertex3f[6*4*3];
13587 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13588 GL_DepthMask(false);
13589 GL_DepthRange(0, 1);
13590 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13591 GL_DepthTest(true);
13592 GL_CullFace(GL_NONE);
13593 R_EntityMatrix(&identitymatrix);
13595 // R_Mesh_ResetTextureState();
13597 i = surfacelist[0];
13598 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13599 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13600 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13601 surfacelist[0] < 0 ? 0.5f : 0.125f);
13603 if (VectorCompare(loc->mins, loc->maxs))
13605 VectorSet(size, 2, 2, 2);
13606 VectorMA(loc->mins, -0.5f, size, mins);
13610 VectorCopy(loc->mins, mins);
13611 VectorSubtract(loc->maxs, loc->mins, size);
13614 for (i = 0;i < 6*4*3;)
13615 for (j = 0;j < 3;j++, i++)
13616 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13618 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13619 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13620 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13623 void R_DrawLocs(void)
13626 cl_locnode_t *loc, *nearestloc;
13628 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13629 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13631 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13632 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13636 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13638 if (decalsystem->decals)
13639 Mem_Free(decalsystem->decals);
13640 memset(decalsystem, 0, sizeof(*decalsystem));
13643 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)
13646 tridecal_t *decals;
13649 // expand or initialize the system
13650 if (decalsystem->maxdecals <= decalsystem->numdecals)
13652 decalsystem_t old = *decalsystem;
13653 qboolean useshortelements;
13654 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13655 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13656 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)));
13657 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13658 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13659 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13660 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13661 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13662 if (decalsystem->numdecals)
13663 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13665 Mem_Free(old.decals);
13666 for (i = 0;i < decalsystem->maxdecals*3;i++)
13667 decalsystem->element3i[i] = i;
13668 if (useshortelements)
13669 for (i = 0;i < decalsystem->maxdecals*3;i++)
13670 decalsystem->element3s[i] = i;
13673 // grab a decal and search for another free slot for the next one
13674 decals = decalsystem->decals;
13675 decal = decalsystem->decals + (i = decalsystem->freedecal++);
13676 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13678 decalsystem->freedecal = i;
13679 if (decalsystem->numdecals <= i)
13680 decalsystem->numdecals = i + 1;
13682 // initialize the decal
13684 decal->triangleindex = triangleindex;
13685 decal->surfaceindex = surfaceindex;
13686 decal->decalsequence = decalsequence;
13687 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13688 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13689 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13690 decal->color4ub[0][3] = 255;
13691 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13692 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13693 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13694 decal->color4ub[1][3] = 255;
13695 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13696 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13697 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13698 decal->color4ub[2][3] = 255;
13699 decal->vertex3f[0][0] = v0[0];
13700 decal->vertex3f[0][1] = v0[1];
13701 decal->vertex3f[0][2] = v0[2];
13702 decal->vertex3f[1][0] = v1[0];
13703 decal->vertex3f[1][1] = v1[1];
13704 decal->vertex3f[1][2] = v1[2];
13705 decal->vertex3f[2][0] = v2[0];
13706 decal->vertex3f[2][1] = v2[1];
13707 decal->vertex3f[2][2] = v2[2];
13708 decal->texcoord2f[0][0] = t0[0];
13709 decal->texcoord2f[0][1] = t0[1];
13710 decal->texcoord2f[1][0] = t1[0];
13711 decal->texcoord2f[1][1] = t1[1];
13712 decal->texcoord2f[2][0] = t2[0];
13713 decal->texcoord2f[2][1] = t2[1];
13716 extern cvar_t cl_decals_bias;
13717 extern cvar_t cl_decals_models;
13718 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13719 // baseparms, parms, temps
13720 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)
13725 const float *vertex3f;
13727 float points[2][9][3];
13734 e = rsurface.modelelement3i + 3*triangleindex;
13736 vertex3f = rsurface.modelvertex3f;
13738 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13740 index = 3*e[cornerindex];
13741 VectorCopy(vertex3f + index, v[cornerindex]);
13744 //TriangleNormal(v[0], v[1], v[2], normal);
13745 //if (DotProduct(normal, localnormal) < 0.0f)
13747 // clip by each of the box planes formed from the projection matrix
13748 // if anything survives, we emit the decal
13749 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]);
13752 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]);
13755 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]);
13758 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]);
13761 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]);
13764 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]);
13767 // some part of the triangle survived, so we have to accept it...
13770 // dynamic always uses the original triangle
13772 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13774 index = 3*e[cornerindex];
13775 VectorCopy(vertex3f + index, v[cornerindex]);
13778 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13780 // convert vertex positions to texcoords
13781 Matrix4x4_Transform(projection, v[cornerindex], temp);
13782 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13783 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13784 // calculate distance fade from the projection origin
13785 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13786 f = bound(0.0f, f, 1.0f);
13787 c[cornerindex][0] = r * f;
13788 c[cornerindex][1] = g * f;
13789 c[cornerindex][2] = b * f;
13790 c[cornerindex][3] = 1.0f;
13791 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13794 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);
13796 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13797 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);
13799 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)
13801 matrix4x4_t projection;
13802 decalsystem_t *decalsystem;
13805 const msurface_t *surface;
13806 const msurface_t *surfaces;
13807 const int *surfacelist;
13808 const texture_t *texture;
13810 int numsurfacelist;
13811 int surfacelistindex;
13814 float localorigin[3];
13815 float localnormal[3];
13816 float localmins[3];
13817 float localmaxs[3];
13820 float planes[6][4];
13823 int bih_triangles_count;
13824 int bih_triangles[256];
13825 int bih_surfaces[256];
13827 decalsystem = &ent->decalsystem;
13828 model = ent->model;
13829 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13831 R_DecalSystem_Reset(&ent->decalsystem);
13835 if (!model->brush.data_leafs && !cl_decals_models.integer)
13837 if (decalsystem->model)
13838 R_DecalSystem_Reset(decalsystem);
13842 if (decalsystem->model != model)
13843 R_DecalSystem_Reset(decalsystem);
13844 decalsystem->model = model;
13846 RSurf_ActiveModelEntity(ent, false, false, false);
13848 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13849 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13850 VectorNormalize(localnormal);
13851 localsize = worldsize*rsurface.inversematrixscale;
13852 localmins[0] = localorigin[0] - localsize;
13853 localmins[1] = localorigin[1] - localsize;
13854 localmins[2] = localorigin[2] - localsize;
13855 localmaxs[0] = localorigin[0] + localsize;
13856 localmaxs[1] = localorigin[1] + localsize;
13857 localmaxs[2] = localorigin[2] + localsize;
13859 //VectorCopy(localnormal, planes[4]);
13860 //VectorVectors(planes[4], planes[2], planes[0]);
13861 AnglesFromVectors(angles, localnormal, NULL, false);
13862 AngleVectors(angles, planes[0], planes[2], planes[4]);
13863 VectorNegate(planes[0], planes[1]);
13864 VectorNegate(planes[2], planes[3]);
13865 VectorNegate(planes[4], planes[5]);
13866 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13867 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13868 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13869 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13870 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13871 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13876 matrix4x4_t forwardprojection;
13877 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13878 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13883 float projectionvector[4][3];
13884 VectorScale(planes[0], ilocalsize, projectionvector[0]);
13885 VectorScale(planes[2], ilocalsize, projectionvector[1]);
13886 VectorScale(planes[4], ilocalsize, projectionvector[2]);
13887 projectionvector[0][0] = planes[0][0] * ilocalsize;
13888 projectionvector[0][1] = planes[1][0] * ilocalsize;
13889 projectionvector[0][2] = planes[2][0] * ilocalsize;
13890 projectionvector[1][0] = planes[0][1] * ilocalsize;
13891 projectionvector[1][1] = planes[1][1] * ilocalsize;
13892 projectionvector[1][2] = planes[2][1] * ilocalsize;
13893 projectionvector[2][0] = planes[0][2] * ilocalsize;
13894 projectionvector[2][1] = planes[1][2] * ilocalsize;
13895 projectionvector[2][2] = planes[2][2] * ilocalsize;
13896 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13897 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13898 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13899 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13903 dynamic = model->surfmesh.isanimated;
13904 numsurfacelist = model->nummodelsurfaces;
13905 surfacelist = model->sortedmodelsurfaces;
13906 surfaces = model->data_surfaces;
13909 bih_triangles_count = -1;
13912 if(model->render_bih.numleafs)
13913 bih = &model->render_bih;
13914 else if(model->collision_bih.numleafs)
13915 bih = &model->collision_bih;
13918 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13919 if(bih_triangles_count == 0)
13921 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13923 if(bih_triangles_count > 0)
13925 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13927 surfaceindex = bih_surfaces[triangleindex];
13928 surface = surfaces + surfaceindex;
13929 texture = surface->texture;
13930 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13932 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13934 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13939 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13941 surfaceindex = surfacelist[surfacelistindex];
13942 surface = surfaces + surfaceindex;
13943 // check cull box first because it rejects more than any other check
13944 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13946 // skip transparent surfaces
13947 texture = surface->texture;
13948 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13950 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13952 numtriangles = surface->num_triangles;
13953 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13954 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13959 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13960 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)
13962 int renderentityindex;
13963 float worldmins[3];
13964 float worldmaxs[3];
13965 entity_render_t *ent;
13967 if (!cl_decals_newsystem.integer)
13970 worldmins[0] = worldorigin[0] - worldsize;
13971 worldmins[1] = worldorigin[1] - worldsize;
13972 worldmins[2] = worldorigin[2] - worldsize;
13973 worldmaxs[0] = worldorigin[0] + worldsize;
13974 worldmaxs[1] = worldorigin[1] + worldsize;
13975 worldmaxs[2] = worldorigin[2] + worldsize;
13977 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13979 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13981 ent = r_refdef.scene.entities[renderentityindex];
13982 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13985 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13989 typedef struct r_decalsystem_splatqueue_s
13991 vec3_t worldorigin;
13992 vec3_t worldnormal;
13998 r_decalsystem_splatqueue_t;
14000 int r_decalsystem_numqueued = 0;
14001 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
14003 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)
14005 r_decalsystem_splatqueue_t *queue;
14007 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
14010 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
14011 VectorCopy(worldorigin, queue->worldorigin);
14012 VectorCopy(worldnormal, queue->worldnormal);
14013 Vector4Set(queue->color, r, g, b, a);
14014 Vector4Set(queue->tcrange, s1, t1, s2, t2);
14015 queue->worldsize = worldsize;
14016 queue->decalsequence = cl.decalsequence++;
14019 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
14022 r_decalsystem_splatqueue_t *queue;
14024 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
14025 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);
14026 r_decalsystem_numqueued = 0;
14029 extern cvar_t cl_decals_max;
14030 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
14033 decalsystem_t *decalsystem = &ent->decalsystem;
14040 if (!decalsystem->numdecals)
14043 if (r_showsurfaces.integer)
14046 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
14048 R_DecalSystem_Reset(decalsystem);
14052 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
14053 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
14055 if (decalsystem->lastupdatetime)
14056 frametime = (cl.time - decalsystem->lastupdatetime);
14059 decalsystem->lastupdatetime = cl.time;
14060 decal = decalsystem->decals;
14061 numdecals = decalsystem->numdecals;
14063 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
14065 if (decal->color4ub[0][3])
14067 decal->lived += frametime;
14068 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
14070 memset(decal, 0, sizeof(*decal));
14071 if (decalsystem->freedecal > i)
14072 decalsystem->freedecal = i;
14076 decal = decalsystem->decals;
14077 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
14080 // collapse the array by shuffling the tail decals into the gaps
14083 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
14084 decalsystem->freedecal++;
14085 if (decalsystem->freedecal == numdecals)
14087 decal[decalsystem->freedecal] = decal[--numdecals];
14090 decalsystem->numdecals = numdecals;
14092 if (numdecals <= 0)
14094 // if there are no decals left, reset decalsystem
14095 R_DecalSystem_Reset(decalsystem);
14099 extern skinframe_t *decalskinframe;
14100 static void R_DrawModelDecals_Entity(entity_render_t *ent)
14103 decalsystem_t *decalsystem = &ent->decalsystem;
14112 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
14115 numdecals = decalsystem->numdecals;
14119 if (r_showsurfaces.integer)
14122 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
14124 R_DecalSystem_Reset(decalsystem);
14128 // if the model is static it doesn't matter what value we give for
14129 // wantnormals and wanttangents, so this logic uses only rules applicable
14130 // to a model, knowing that they are meaningless otherwise
14131 if (ent == r_refdef.scene.worldentity)
14132 RSurf_ActiveWorldEntity();
14134 RSurf_ActiveModelEntity(ent, false, false, false);
14136 decalsystem->lastupdatetime = cl.time;
14137 decal = decalsystem->decals;
14139 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
14141 // update vertex positions for animated models
14142 v3f = decalsystem->vertex3f;
14143 c4f = decalsystem->color4f;
14144 t2f = decalsystem->texcoord2f;
14145 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
14147 if (!decal->color4ub[0][3])
14150 if (surfacevisible && !surfacevisible[decal->surfaceindex])
14153 // update color values for fading decals
14154 if (decal->lived >= cl_decals_time.value)
14156 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
14157 alpha *= (1.0f/255.0f);
14160 alpha = 1.0f/255.0f;
14162 c4f[ 0] = decal->color4ub[0][0] * alpha;
14163 c4f[ 1] = decal->color4ub[0][1] * alpha;
14164 c4f[ 2] = decal->color4ub[0][2] * alpha;
14166 c4f[ 4] = decal->color4ub[1][0] * alpha;
14167 c4f[ 5] = decal->color4ub[1][1] * alpha;
14168 c4f[ 6] = decal->color4ub[1][2] * alpha;
14170 c4f[ 8] = decal->color4ub[2][0] * alpha;
14171 c4f[ 9] = decal->color4ub[2][1] * alpha;
14172 c4f[10] = decal->color4ub[2][2] * alpha;
14175 t2f[0] = decal->texcoord2f[0][0];
14176 t2f[1] = decal->texcoord2f[0][1];
14177 t2f[2] = decal->texcoord2f[1][0];
14178 t2f[3] = decal->texcoord2f[1][1];
14179 t2f[4] = decal->texcoord2f[2][0];
14180 t2f[5] = decal->texcoord2f[2][1];
14182 // update vertex positions for animated models
14183 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
14185 e = rsurface.modelelement3i + 3*decal->triangleindex;
14186 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
14187 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
14188 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
14192 VectorCopy(decal->vertex3f[0], v3f);
14193 VectorCopy(decal->vertex3f[1], v3f + 3);
14194 VectorCopy(decal->vertex3f[2], v3f + 6);
14197 if (r_refdef.fogenabled)
14199 alpha = RSurf_FogVertex(v3f);
14200 VectorScale(c4f, alpha, c4f);
14201 alpha = RSurf_FogVertex(v3f + 3);
14202 VectorScale(c4f + 4, alpha, c4f + 4);
14203 alpha = RSurf_FogVertex(v3f + 6);
14204 VectorScale(c4f + 8, alpha, c4f + 8);
14215 r_refdef.stats.drawndecals += numtris;
14217 // now render the decals all at once
14218 // (this assumes they all use one particle font texture!)
14219 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);
14220 // R_Mesh_ResetTextureState();
14221 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
14222 GL_DepthMask(false);
14223 GL_DepthRange(0, 1);
14224 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
14225 GL_DepthTest(true);
14226 GL_CullFace(GL_NONE);
14227 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
14228 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
14229 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
14233 static void R_DrawModelDecals(void)
14237 // fade faster when there are too many decals
14238 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14239 for (i = 0;i < r_refdef.scene.numentities;i++)
14240 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14242 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
14243 for (i = 0;i < r_refdef.scene.numentities;i++)
14244 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14245 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
14247 R_DecalSystem_ApplySplatEntitiesQueue();
14249 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14250 for (i = 0;i < r_refdef.scene.numentities;i++)
14251 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14253 r_refdef.stats.totaldecals += numdecals;
14255 if (r_showsurfaces.integer)
14258 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
14260 for (i = 0;i < r_refdef.scene.numentities;i++)
14262 if (!r_refdef.viewcache.entityvisible[i])
14264 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14265 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
14269 extern cvar_t mod_collision_bih;
14270 void R_DrawDebugModel(void)
14272 entity_render_t *ent = rsurface.entity;
14273 int i, j, k, l, flagsmask;
14274 const msurface_t *surface;
14275 dp_model_t *model = ent->model;
14278 switch(vid.renderpath)
14280 case RENDERPATH_GL11:
14281 case RENDERPATH_GL13:
14282 case RENDERPATH_GL20:
14283 case RENDERPATH_CGGL:
14285 case RENDERPATH_D3D9:
14286 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14288 case RENDERPATH_D3D10:
14289 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14291 case RENDERPATH_D3D11:
14292 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14294 case RENDERPATH_SOFT:
14295 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14299 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
14301 // R_Mesh_ResetTextureState();
14302 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
14303 GL_DepthRange(0, 1);
14304 GL_DepthTest(!r_showdisabledepthtest.integer);
14305 GL_DepthMask(false);
14306 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14308 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
14312 qboolean cullbox = ent == r_refdef.scene.worldentity;
14313 const q3mbrush_t *brush;
14314 const bih_t *bih = &model->collision_bih;
14315 const bih_leaf_t *bihleaf;
14316 float vertex3f[3][3];
14317 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
14319 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
14321 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
14323 switch (bihleaf->type)
14326 brush = model->brush.data_brushes + bihleaf->itemindex;
14327 if (brush->colbrushf && brush->colbrushf->numtriangles)
14329 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);
14330 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
14331 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
14334 case BIH_COLLISIONTRIANGLE:
14335 triangleindex = bihleaf->itemindex;
14336 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
14337 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
14338 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
14339 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);
14340 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14341 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14343 case BIH_RENDERTRIANGLE:
14344 triangleindex = bihleaf->itemindex;
14345 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
14346 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
14347 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
14348 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);
14349 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14350 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14356 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
14358 if (r_showtris.integer || (r_shownormals.value != 0))
14360 if (r_showdisabledepthtest.integer)
14362 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14363 GL_DepthMask(false);
14367 GL_BlendFunc(GL_ONE, GL_ZERO);
14368 GL_DepthMask(true);
14370 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
14372 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
14374 rsurface.texture = R_GetCurrentTexture(surface->texture);
14375 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
14377 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
14378 if (r_showtris.value > 0)
14380 if (!rsurface.texture->currentlayers->depthmask)
14381 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
14382 else if (ent == r_refdef.scene.worldentity)
14383 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
14385 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
14386 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
14387 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
14389 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
14392 if (r_shownormals.value < 0)
14394 qglBegin(GL_LINES);
14395 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14397 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14398 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14399 qglVertex3f(v[0], v[1], v[2]);
14400 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14401 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14402 qglVertex3f(v[0], v[1], v[2]);
14407 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
14409 qglBegin(GL_LINES);
14410 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14412 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14413 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14414 qglVertex3f(v[0], v[1], v[2]);
14415 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14416 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14417 qglVertex3f(v[0], v[1], v[2]);
14421 qglBegin(GL_LINES);
14422 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14424 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14425 GL_Color(0, r_refdef.view.colorscale, 0, 1);
14426 qglVertex3f(v[0], v[1], v[2]);
14427 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
14428 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14429 qglVertex3f(v[0], v[1], v[2]);
14433 qglBegin(GL_LINES);
14434 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14436 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14437 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14438 qglVertex3f(v[0], v[1], v[2]);
14439 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14440 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14441 qglVertex3f(v[0], v[1], v[2]);
14448 rsurface.texture = NULL;
14452 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
14453 int r_maxsurfacelist = 0;
14454 const msurface_t **r_surfacelist = NULL;
14455 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14457 int i, j, endj, flagsmask;
14458 dp_model_t *model = r_refdef.scene.worldmodel;
14459 msurface_t *surfaces;
14460 unsigned char *update;
14461 int numsurfacelist = 0;
14465 if (r_maxsurfacelist < model->num_surfaces)
14467 r_maxsurfacelist = model->num_surfaces;
14469 Mem_Free((msurface_t**)r_surfacelist);
14470 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14473 RSurf_ActiveWorldEntity();
14475 surfaces = model->data_surfaces;
14476 update = model->brushq1.lightmapupdateflags;
14478 // update light styles on this submodel
14479 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14481 model_brush_lightstyleinfo_t *style;
14482 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14484 if (style->value != r_refdef.scene.lightstylevalue[style->style])
14486 int *list = style->surfacelist;
14487 style->value = r_refdef.scene.lightstylevalue[style->style];
14488 for (j = 0;j < style->numsurfaces;j++)
14489 update[list[j]] = true;
14494 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14498 R_DrawDebugModel();
14499 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14503 rsurface.lightmaptexture = NULL;
14504 rsurface.deluxemaptexture = NULL;
14505 rsurface.uselightmaptexture = false;
14506 rsurface.texture = NULL;
14507 rsurface.rtlight = NULL;
14508 numsurfacelist = 0;
14509 // add visible surfaces to draw list
14510 for (i = 0;i < model->nummodelsurfaces;i++)
14512 j = model->sortedmodelsurfaces[i];
14513 if (r_refdef.viewcache.world_surfacevisible[j])
14514 r_surfacelist[numsurfacelist++] = surfaces + j;
14516 // update lightmaps if needed
14517 if (model->brushq1.firstrender)
14519 model->brushq1.firstrender = false;
14520 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14522 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14526 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14527 if (r_refdef.viewcache.world_surfacevisible[j])
14529 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14531 // don't do anything if there were no surfaces
14532 if (!numsurfacelist)
14534 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14537 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14538 GL_AlphaTest(false);
14540 // add to stats if desired
14541 if (r_speeds.integer && !skysurfaces && !depthonly)
14543 r_refdef.stats.world_surfaces += numsurfacelist;
14544 for (j = 0;j < numsurfacelist;j++)
14545 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
14548 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14551 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14553 int i, j, endj, flagsmask;
14554 dp_model_t *model = ent->model;
14555 msurface_t *surfaces;
14556 unsigned char *update;
14557 int numsurfacelist = 0;
14561 if (r_maxsurfacelist < model->num_surfaces)
14563 r_maxsurfacelist = model->num_surfaces;
14565 Mem_Free((msurface_t **)r_surfacelist);
14566 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14569 // if the model is static it doesn't matter what value we give for
14570 // wantnormals and wanttangents, so this logic uses only rules applicable
14571 // to a model, knowing that they are meaningless otherwise
14572 if (ent == r_refdef.scene.worldentity)
14573 RSurf_ActiveWorldEntity();
14574 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14575 RSurf_ActiveModelEntity(ent, false, false, false);
14577 RSurf_ActiveModelEntity(ent, true, true, true);
14578 else if (depthonly)
14580 switch (vid.renderpath)
14582 case RENDERPATH_GL20:
14583 case RENDERPATH_CGGL:
14584 case RENDERPATH_D3D9:
14585 case RENDERPATH_D3D10:
14586 case RENDERPATH_D3D11:
14587 case RENDERPATH_SOFT:
14588 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14590 case RENDERPATH_GL13:
14591 case RENDERPATH_GL11:
14592 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14598 switch (vid.renderpath)
14600 case RENDERPATH_GL20:
14601 case RENDERPATH_CGGL:
14602 case RENDERPATH_D3D9:
14603 case RENDERPATH_D3D10:
14604 case RENDERPATH_D3D11:
14605 case RENDERPATH_SOFT:
14606 RSurf_ActiveModelEntity(ent, true, true, false);
14608 case RENDERPATH_GL13:
14609 case RENDERPATH_GL11:
14610 RSurf_ActiveModelEntity(ent, true, false, false);
14615 surfaces = model->data_surfaces;
14616 update = model->brushq1.lightmapupdateflags;
14618 // update light styles
14619 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14621 model_brush_lightstyleinfo_t *style;
14622 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14624 if (style->value != r_refdef.scene.lightstylevalue[style->style])
14626 int *list = style->surfacelist;
14627 style->value = r_refdef.scene.lightstylevalue[style->style];
14628 for (j = 0;j < style->numsurfaces;j++)
14629 update[list[j]] = true;
14634 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14638 R_DrawDebugModel();
14639 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14643 rsurface.lightmaptexture = NULL;
14644 rsurface.deluxemaptexture = NULL;
14645 rsurface.uselightmaptexture = false;
14646 rsurface.texture = NULL;
14647 rsurface.rtlight = NULL;
14648 numsurfacelist = 0;
14649 // add visible surfaces to draw list
14650 for (i = 0;i < model->nummodelsurfaces;i++)
14651 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14652 // don't do anything if there were no surfaces
14653 if (!numsurfacelist)
14655 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14658 // update lightmaps if needed
14662 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14667 R_BuildLightMap(ent, surfaces + j);
14672 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14674 R_BuildLightMap(ent, surfaces + j);
14675 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14676 GL_AlphaTest(false);
14678 // add to stats if desired
14679 if (r_speeds.integer && !skysurfaces && !depthonly)
14681 r_refdef.stats.entities_surfaces += numsurfacelist;
14682 for (j = 0;j < numsurfacelist;j++)
14683 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14686 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14689 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14691 static texture_t texture;
14692 static msurface_t surface;
14693 const msurface_t *surfacelist = &surface;
14695 // fake enough texture and surface state to render this geometry
14697 texture.update_lastrenderframe = -1; // regenerate this texture
14698 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14699 texture.currentskinframe = skinframe;
14700 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14701 texture.offsetmapping = OFFSETMAPPING_OFF;
14702 texture.offsetscale = 1;
14703 texture.specularscalemod = 1;
14704 texture.specularpowermod = 1;
14706 surface.texture = &texture;
14707 surface.num_triangles = numtriangles;
14708 surface.num_firsttriangle = firsttriangle;
14709 surface.num_vertices = numvertices;
14710 surface.num_firstvertex = firstvertex;
14713 rsurface.texture = R_GetCurrentTexture(surface.texture);
14714 rsurface.lightmaptexture = NULL;
14715 rsurface.deluxemaptexture = NULL;
14716 rsurface.uselightmaptexture = false;
14717 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14720 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)
14722 static msurface_t surface;
14723 const msurface_t *surfacelist = &surface;
14725 // fake enough texture and surface state to render this geometry
14726 surface.texture = texture;
14727 surface.num_triangles = numtriangles;
14728 surface.num_firsttriangle = firsttriangle;
14729 surface.num_vertices = numvertices;
14730 surface.num_firstvertex = firstvertex;
14733 rsurface.texture = R_GetCurrentTexture(surface.texture);
14734 rsurface.lightmaptexture = NULL;
14735 rsurface.deluxemaptexture = NULL;
14736 rsurface.uselightmaptexture = false;
14737 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);