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 exaggerated 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 (equivalent 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 accordingly, 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_NORMAL , rsurface.texture->nmaptexture );
6252 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
6253 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
6254 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
6255 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
6256 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
6257 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
6258 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
6259 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
6260 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
6261 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
6262 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
6263 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
6264 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
6265 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
6266 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
6267 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
6268 if (rsurfacepass == RSURFPASS_BACKGROUND)
6270 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
6271 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
6272 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
6276 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
6278 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
6279 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
6280 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
6281 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
6282 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6284 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
6285 if (rsurface.rtlight)
6287 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
6288 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
6295 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6297 // select a permutation of the lighting shader appropriate to this
6298 // combination of texture, entity, light source, and fogging, only use the
6299 // minimum features necessary to avoid wasting rendering time in the
6300 // fragment shader on features that are not being used
6301 unsigned int permutation = 0;
6302 unsigned int mode = 0;
6303 const float *lightcolorbase = rtlight->currentcolor;
6304 float ambientscale = rtlight->ambientscale;
6305 float diffusescale = rtlight->diffusescale;
6306 float specularscale = rtlight->specularscale;
6307 // this is the location of the light in view space
6308 vec3_t viewlightorigin;
6309 // this transforms from view space (camera) to light space (cubemap)
6310 matrix4x4_t viewtolight;
6311 matrix4x4_t lighttoview;
6312 float viewtolight16f[16];
6313 float range = 1.0f / r_shadow_deferred_8bitrange.value;
6315 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6316 if (rtlight->currentcubemap != r_texture_whitecube)
6317 permutation |= SHADERPERMUTATION_CUBEFILTER;
6318 if (diffusescale > 0)
6319 permutation |= SHADERPERMUTATION_DIFFUSE;
6320 if (specularscale > 0)
6321 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6322 if (r_shadow_usingshadowmap2d)
6324 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6325 if (r_shadow_shadowmapvsdct)
6326 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6328 if (r_shadow_shadowmapsampler)
6329 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6330 if (r_shadow_shadowmappcf > 1)
6331 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6332 else if (r_shadow_shadowmappcf)
6333 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6335 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6336 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6337 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6338 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6339 switch(vid.renderpath)
6341 case RENDERPATH_D3D9:
6343 R_SetupShader_SetPermutationHLSL(mode, permutation);
6344 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6345 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6346 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
6347 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
6348 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6349 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6350 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6351 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6352 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6353 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6355 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
6356 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
6357 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
6358 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
6359 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
6360 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
6363 case RENDERPATH_D3D10:
6364 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6366 case RENDERPATH_D3D11:
6367 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6369 case RENDERPATH_GL20:
6370 R_SetupShader_SetPermutationGLSL(mode, permutation);
6371 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6372 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
6373 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);
6374 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);
6375 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);
6376 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]);
6377 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]);
6378 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));
6379 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]);
6380 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6382 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
6383 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
6384 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
6385 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
6386 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
6387 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
6389 case RENDERPATH_CGGL:
6391 R_SetupShader_SetPermutationCG(mode, permutation);
6392 if (r_cg_permutation->fp_LightPosition ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6393 if (r_cg_permutation->fp_ViewToLight ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6394 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
6395 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
6396 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
6397 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
6398 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
6399 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
6400 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
6401 if (r_cg_permutation->fp_PixelToScreenTexCoord ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6403 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
6404 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
6405 if (r_cg_permutation->fp_Texture_ScreenNormalMap ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
6406 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
6407 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
6408 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
6411 case RENDERPATH_GL13:
6412 case RENDERPATH_GL11:
6414 case RENDERPATH_SOFT:
6415 R_SetupShader_SetPermutationGLSL(mode, permutation);
6416 DPSOFTRAST_Uniform3fARB( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6417 DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
6418 DPSOFTRAST_Uniform3fARB( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
6419 DPSOFTRAST_Uniform3fARB( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
6420 DPSOFTRAST_Uniform3fARB( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6421 DPSOFTRAST_Uniform2fARB( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6422 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]);
6423 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));
6424 DPSOFTRAST_Uniform2fARB( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6425 DPSOFTRAST_Uniform2fARB(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6427 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
6428 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
6429 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
6430 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
6431 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
6432 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
6437 #define SKINFRAME_HASH 1024
6441 int loadsequence; // incremented each level change
6442 memexpandablearray_t array;
6443 skinframe_t *hash[SKINFRAME_HASH];
6446 r_skinframe_t r_skinframe;
6448 void R_SkinFrame_PrepareForPurge(void)
6450 r_skinframe.loadsequence++;
6451 // wrap it without hitting zero
6452 if (r_skinframe.loadsequence >= 200)
6453 r_skinframe.loadsequence = 1;
6456 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6460 // mark the skinframe as used for the purging code
6461 skinframe->loadsequence = r_skinframe.loadsequence;
6464 void R_SkinFrame_Purge(void)
6468 for (i = 0;i < SKINFRAME_HASH;i++)
6470 for (s = r_skinframe.hash[i];s;s = s->next)
6472 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6474 if (s->merged == s->base)
6476 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6477 R_PurgeTexture(s->stain );s->stain = NULL;
6478 R_PurgeTexture(s->merged);s->merged = NULL;
6479 R_PurgeTexture(s->base );s->base = NULL;
6480 R_PurgeTexture(s->pants );s->pants = NULL;
6481 R_PurgeTexture(s->shirt );s->shirt = NULL;
6482 R_PurgeTexture(s->nmap );s->nmap = NULL;
6483 R_PurgeTexture(s->gloss );s->gloss = NULL;
6484 R_PurgeTexture(s->glow );s->glow = NULL;
6485 R_PurgeTexture(s->fog );s->fog = NULL;
6486 R_PurgeTexture(s->reflect);s->reflect = NULL;
6487 s->loadsequence = 0;
6493 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6495 char basename[MAX_QPATH];
6497 Image_StripImageExtension(name, basename, sizeof(basename));
6499 if( last == NULL ) {
6501 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6502 item = r_skinframe.hash[hashindex];
6507 // linearly search through the hash bucket
6508 for( ; item ; item = item->next ) {
6509 if( !strcmp( item->basename, basename ) ) {
6516 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6520 char basename[MAX_QPATH];
6522 Image_StripImageExtension(name, basename, sizeof(basename));
6524 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6525 for (item = r_skinframe.hash[hashindex];item;item = item->next)
6526 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6530 rtexture_t *dyntexture;
6531 // check whether its a dynamic texture
6532 dyntexture = CL_GetDynTexture( basename );
6533 if (!add && !dyntexture)
6535 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6536 memset(item, 0, sizeof(*item));
6537 strlcpy(item->basename, basename, sizeof(item->basename));
6538 item->base = dyntexture; // either NULL or dyntexture handle
6539 item->textureflags = textureflags;
6540 item->comparewidth = comparewidth;
6541 item->compareheight = compareheight;
6542 item->comparecrc = comparecrc;
6543 item->next = r_skinframe.hash[hashindex];
6544 r_skinframe.hash[hashindex] = item;
6546 else if( item->base == NULL )
6548 rtexture_t *dyntexture;
6549 // check whether its a dynamic texture
6550 // 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]
6551 dyntexture = CL_GetDynTexture( basename );
6552 item->base = dyntexture; // either NULL or dyntexture handle
6555 R_SkinFrame_MarkUsed(item);
6559 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6561 unsigned long long avgcolor[5], wsum; \
6569 for(pix = 0; pix < cnt; ++pix) \
6572 for(comp = 0; comp < 3; ++comp) \
6574 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6577 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6579 for(comp = 0; comp < 3; ++comp) \
6580 avgcolor[comp] += getpixel * w; \
6583 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6584 avgcolor[4] += getpixel; \
6586 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6588 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6589 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6590 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6591 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6594 extern cvar_t gl_picmip;
6595 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6598 unsigned char *pixels;
6599 unsigned char *bumppixels;
6600 unsigned char *basepixels = NULL;
6601 int basepixels_width = 0;
6602 int basepixels_height = 0;
6603 skinframe_t *skinframe;
6604 rtexture_t *ddsbase = NULL;
6605 qboolean ddshasalpha = false;
6606 float ddsavgcolor[4];
6607 char basename[MAX_QPATH];
6608 int miplevel = R_PicmipForFlags(textureflags);
6609 int savemiplevel = miplevel;
6612 if (cls.state == ca_dedicated)
6615 // return an existing skinframe if already loaded
6616 // if loading of the first image fails, don't make a new skinframe as it
6617 // would cause all future lookups of this to be missing
6618 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6619 if (skinframe && skinframe->base)
6622 Image_StripImageExtension(name, basename, sizeof(basename));
6624 // check for DDS texture file first
6625 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6627 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6628 if (basepixels == NULL)
6632 // FIXME handle miplevel
6634 if (developer_loading.integer)
6635 Con_Printf("loading skin \"%s\"\n", name);
6637 // we've got some pixels to store, so really allocate this new texture now
6639 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6640 skinframe->stain = NULL;
6641 skinframe->merged = NULL;
6642 skinframe->base = NULL;
6643 skinframe->pants = NULL;
6644 skinframe->shirt = NULL;
6645 skinframe->nmap = NULL;
6646 skinframe->gloss = NULL;
6647 skinframe->glow = NULL;
6648 skinframe->fog = NULL;
6649 skinframe->reflect = NULL;
6650 skinframe->hasalpha = false;
6654 skinframe->base = ddsbase;
6655 skinframe->hasalpha = ddshasalpha;
6656 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6657 if (r_loadfog && skinframe->hasalpha)
6658 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6659 //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]);
6663 basepixels_width = image_width;
6664 basepixels_height = image_height;
6665 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);
6666 if (textureflags & TEXF_ALPHA)
6668 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6670 if (basepixels[j] < 255)
6672 skinframe->hasalpha = true;
6676 if (r_loadfog && skinframe->hasalpha)
6678 // has transparent pixels
6679 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6680 for (j = 0;j < image_width * image_height * 4;j += 4)
6685 pixels[j+3] = basepixels[j+3];
6687 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);
6691 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6692 //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]);
6693 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6694 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6695 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6696 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6701 mymiplevel = savemiplevel;
6702 if (r_loadnormalmap)
6703 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);
6704 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6706 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6707 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6708 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6709 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6712 // _norm is the name used by tenebrae and has been adopted as standard
6713 if (r_loadnormalmap && skinframe->nmap == NULL)
6715 mymiplevel = savemiplevel;
6716 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6718 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);
6722 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6724 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6725 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6726 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);
6728 Mem_Free(bumppixels);
6730 else if (r_shadow_bumpscale_basetexture.value > 0)
6732 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6733 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6734 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);
6737 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6738 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6741 // _luma is supported only for tenebrae compatibility
6742 // _glow is the preferred name
6743 mymiplevel = savemiplevel;
6744 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))))
6746 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);
6747 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6748 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6749 Mem_Free(pixels);pixels = NULL;
6752 mymiplevel = savemiplevel;
6753 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6755 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);
6756 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6757 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6762 mymiplevel = savemiplevel;
6763 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6765 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);
6766 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6767 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6772 mymiplevel = savemiplevel;
6773 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6775 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);
6776 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6777 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6782 mymiplevel = savemiplevel;
6783 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6785 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);
6786 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6787 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6793 Mem_Free(basepixels);
6798 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6799 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6802 unsigned char *temp1, *temp2;
6803 skinframe_t *skinframe;
6805 if (cls.state == ca_dedicated)
6808 // if already loaded just return it, otherwise make a new skinframe
6809 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6810 if (skinframe && skinframe->base)
6813 skinframe->stain = NULL;
6814 skinframe->merged = NULL;
6815 skinframe->base = NULL;
6816 skinframe->pants = NULL;
6817 skinframe->shirt = NULL;
6818 skinframe->nmap = NULL;
6819 skinframe->gloss = NULL;
6820 skinframe->glow = NULL;
6821 skinframe->fog = NULL;
6822 skinframe->reflect = NULL;
6823 skinframe->hasalpha = false;
6825 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6829 if (developer_loading.integer)
6830 Con_Printf("loading 32bit skin \"%s\"\n", name);
6832 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6834 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6835 temp2 = temp1 + width * height * 4;
6836 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6837 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);
6840 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6841 if (textureflags & TEXF_ALPHA)
6843 for (i = 3;i < width * height * 4;i += 4)
6845 if (skindata[i] < 255)
6847 skinframe->hasalpha = true;
6851 if (r_loadfog && skinframe->hasalpha)
6853 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6854 memcpy(fogpixels, skindata, width * height * 4);
6855 for (i = 0;i < width * height * 4;i += 4)
6856 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6857 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6858 Mem_Free(fogpixels);
6862 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6863 //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]);
6868 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6872 skinframe_t *skinframe;
6874 if (cls.state == ca_dedicated)
6877 // if already loaded just return it, otherwise make a new skinframe
6878 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6879 if (skinframe && skinframe->base)
6882 skinframe->stain = NULL;
6883 skinframe->merged = NULL;
6884 skinframe->base = NULL;
6885 skinframe->pants = NULL;
6886 skinframe->shirt = NULL;
6887 skinframe->nmap = NULL;
6888 skinframe->gloss = NULL;
6889 skinframe->glow = NULL;
6890 skinframe->fog = NULL;
6891 skinframe->reflect = NULL;
6892 skinframe->hasalpha = false;
6894 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6898 if (developer_loading.integer)
6899 Con_Printf("loading quake skin \"%s\"\n", name);
6901 // 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)
6902 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
6903 memcpy(skinframe->qpixels, skindata, width*height);
6904 skinframe->qwidth = width;
6905 skinframe->qheight = height;
6908 for (i = 0;i < width * height;i++)
6909 featuresmask |= palette_featureflags[skindata[i]];
6911 skinframe->hasalpha = false;
6912 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6913 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6914 skinframe->qgeneratemerged = true;
6915 skinframe->qgeneratebase = skinframe->qhascolormapping;
6916 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6918 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6919 //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]);
6924 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6928 unsigned char *skindata;
6930 if (!skinframe->qpixels)
6933 if (!skinframe->qhascolormapping)
6934 colormapped = false;
6938 if (!skinframe->qgeneratebase)
6943 if (!skinframe->qgeneratemerged)
6947 width = skinframe->qwidth;
6948 height = skinframe->qheight;
6949 skindata = skinframe->qpixels;
6951 if (skinframe->qgeneratenmap)
6953 unsigned char *temp1, *temp2;
6954 skinframe->qgeneratenmap = false;
6955 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6956 temp2 = temp1 + width * height * 4;
6957 // use either a custom palette or the quake palette
6958 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6959 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6960 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);
6964 if (skinframe->qgenerateglow)
6966 skinframe->qgenerateglow = false;
6967 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6972 skinframe->qgeneratebase = false;
6973 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);
6974 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6975 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6979 skinframe->qgeneratemerged = false;
6980 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);
6983 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6985 Mem_Free(skinframe->qpixels);
6986 skinframe->qpixels = NULL;
6990 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)
6993 skinframe_t *skinframe;
6995 if (cls.state == ca_dedicated)
6998 // if already loaded just return it, otherwise make a new skinframe
6999 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
7000 if (skinframe && skinframe->base)
7003 skinframe->stain = NULL;
7004 skinframe->merged = NULL;
7005 skinframe->base = NULL;
7006 skinframe->pants = NULL;
7007 skinframe->shirt = NULL;
7008 skinframe->nmap = NULL;
7009 skinframe->gloss = NULL;
7010 skinframe->glow = NULL;
7011 skinframe->fog = NULL;
7012 skinframe->reflect = NULL;
7013 skinframe->hasalpha = false;
7015 // if no data was provided, then clearly the caller wanted to get a blank skinframe
7019 if (developer_loading.integer)
7020 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
7022 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
7023 if (textureflags & TEXF_ALPHA)
7025 for (i = 0;i < width * height;i++)
7027 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
7029 skinframe->hasalpha = true;
7033 if (r_loadfog && skinframe->hasalpha)
7034 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
7037 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
7038 //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]);
7043 skinframe_t *R_SkinFrame_LoadMissing(void)
7045 skinframe_t *skinframe;
7047 if (cls.state == ca_dedicated)
7050 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
7051 skinframe->stain = NULL;
7052 skinframe->merged = NULL;
7053 skinframe->base = NULL;
7054 skinframe->pants = NULL;
7055 skinframe->shirt = NULL;
7056 skinframe->nmap = NULL;
7057 skinframe->gloss = NULL;
7058 skinframe->glow = NULL;
7059 skinframe->fog = NULL;
7060 skinframe->reflect = NULL;
7061 skinframe->hasalpha = false;
7063 skinframe->avgcolor[0] = rand() / RAND_MAX;
7064 skinframe->avgcolor[1] = rand() / RAND_MAX;
7065 skinframe->avgcolor[2] = rand() / RAND_MAX;
7066 skinframe->avgcolor[3] = 1;
7071 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
7072 typedef struct suffixinfo_s
7075 qboolean flipx, flipy, flipdiagonal;
7078 static suffixinfo_t suffix[3][6] =
7081 {"px", false, false, false},
7082 {"nx", false, false, false},
7083 {"py", false, false, false},
7084 {"ny", false, false, false},
7085 {"pz", false, false, false},
7086 {"nz", false, false, false}
7089 {"posx", false, false, false},
7090 {"negx", false, false, false},
7091 {"posy", false, false, false},
7092 {"negy", false, false, false},
7093 {"posz", false, false, false},
7094 {"negz", false, false, false}
7097 {"rt", true, false, true},
7098 {"lf", false, true, true},
7099 {"ft", true, true, false},
7100 {"bk", false, false, false},
7101 {"up", true, false, true},
7102 {"dn", true, false, true}
7106 static int componentorder[4] = {0, 1, 2, 3};
7108 rtexture_t *R_LoadCubemap(const char *basename)
7110 int i, j, cubemapsize;
7111 unsigned char *cubemappixels, *image_buffer;
7112 rtexture_t *cubemaptexture;
7114 // must start 0 so the first loadimagepixels has no requested width/height
7116 cubemappixels = NULL;
7117 cubemaptexture = NULL;
7118 // keep trying different suffix groups (posx, px, rt) until one loads
7119 for (j = 0;j < 3 && !cubemappixels;j++)
7121 // load the 6 images in the suffix group
7122 for (i = 0;i < 6;i++)
7124 // generate an image name based on the base and and suffix
7125 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
7127 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
7129 // an image loaded, make sure width and height are equal
7130 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
7132 // if this is the first image to load successfully, allocate the cubemap memory
7133 if (!cubemappixels && image_width >= 1)
7135 cubemapsize = image_width;
7136 // note this clears to black, so unavailable sides are black
7137 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
7139 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
7141 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);
7144 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
7146 Mem_Free(image_buffer);
7150 // if a cubemap loaded, upload it
7153 if (developer_loading.integer)
7154 Con_Printf("loading cubemap \"%s\"\n", basename);
7156 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
7157 Mem_Free(cubemappixels);
7161 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
7162 if (developer_loading.integer)
7164 Con_Printf("(tried tried images ");
7165 for (j = 0;j < 3;j++)
7166 for (i = 0;i < 6;i++)
7167 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
7168 Con_Print(" and was unable to find any of them).\n");
7171 return cubemaptexture;
7174 rtexture_t *R_GetCubemap(const char *basename)
7177 for (i = 0;i < r_texture_numcubemaps;i++)
7178 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
7179 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
7180 if (i >= MAX_CUBEMAPS)
7181 return r_texture_whitecube;
7182 r_texture_numcubemaps++;
7183 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
7184 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
7185 return r_texture_cubemaps[i].texture;
7188 void R_FreeCubemaps(void)
7191 for (i = 0;i < r_texture_numcubemaps;i++)
7193 if (developer_loading.integer)
7194 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
7195 if (r_texture_cubemaps[i].texture)
7196 R_FreeTexture(r_texture_cubemaps[i].texture);
7198 r_texture_numcubemaps = 0;
7201 void R_Main_FreeViewCache(void)
7203 if (r_refdef.viewcache.entityvisible)
7204 Mem_Free(r_refdef.viewcache.entityvisible);
7205 if (r_refdef.viewcache.world_pvsbits)
7206 Mem_Free(r_refdef.viewcache.world_pvsbits);
7207 if (r_refdef.viewcache.world_leafvisible)
7208 Mem_Free(r_refdef.viewcache.world_leafvisible);
7209 if (r_refdef.viewcache.world_surfacevisible)
7210 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7211 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
7214 void R_Main_ResizeViewCache(void)
7216 int numentities = r_refdef.scene.numentities;
7217 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
7218 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
7219 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
7220 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
7221 if (r_refdef.viewcache.maxentities < numentities)
7223 r_refdef.viewcache.maxentities = numentities;
7224 if (r_refdef.viewcache.entityvisible)
7225 Mem_Free(r_refdef.viewcache.entityvisible);
7226 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
7228 if (r_refdef.viewcache.world_numclusters != numclusters)
7230 r_refdef.viewcache.world_numclusters = numclusters;
7231 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
7232 if (r_refdef.viewcache.world_pvsbits)
7233 Mem_Free(r_refdef.viewcache.world_pvsbits);
7234 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
7236 if (r_refdef.viewcache.world_numleafs != numleafs)
7238 r_refdef.viewcache.world_numleafs = numleafs;
7239 if (r_refdef.viewcache.world_leafvisible)
7240 Mem_Free(r_refdef.viewcache.world_leafvisible);
7241 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
7243 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
7245 r_refdef.viewcache.world_numsurfaces = numsurfaces;
7246 if (r_refdef.viewcache.world_surfacevisible)
7247 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7248 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
7252 extern rtexture_t *loadingscreentexture;
7253 void gl_main_start(void)
7255 loadingscreentexture = NULL;
7256 r_texture_blanknormalmap = NULL;
7257 r_texture_white = NULL;
7258 r_texture_grey128 = NULL;
7259 r_texture_black = NULL;
7260 r_texture_whitecube = NULL;
7261 r_texture_normalizationcube = NULL;
7262 r_texture_fogattenuation = NULL;
7263 r_texture_fogheighttexture = NULL;
7264 r_texture_gammaramps = NULL;
7265 r_texture_numcubemaps = 0;
7267 r_loaddds = r_texture_dds_load.integer != 0;
7268 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
7270 switch(vid.renderpath)
7272 case RENDERPATH_GL20:
7273 case RENDERPATH_CGGL:
7274 case RENDERPATH_D3D9:
7275 case RENDERPATH_D3D10:
7276 case RENDERPATH_D3D11:
7277 case RENDERPATH_SOFT:
7278 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7279 Cvar_SetValueQuick(&gl_combine, 1);
7280 Cvar_SetValueQuick(&r_glsl, 1);
7281 r_loadnormalmap = true;
7285 case RENDERPATH_GL13:
7286 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7287 Cvar_SetValueQuick(&gl_combine, 1);
7288 Cvar_SetValueQuick(&r_glsl, 0);
7289 r_loadnormalmap = false;
7290 r_loadgloss = false;
7293 case RENDERPATH_GL11:
7294 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7295 Cvar_SetValueQuick(&gl_combine, 0);
7296 Cvar_SetValueQuick(&r_glsl, 0);
7297 r_loadnormalmap = false;
7298 r_loadgloss = false;
7304 R_FrameData_Reset();
7308 memset(r_queries, 0, sizeof(r_queries));
7310 r_qwskincache = NULL;
7311 r_qwskincache_size = 0;
7313 // set up r_skinframe loading system for textures
7314 memset(&r_skinframe, 0, sizeof(r_skinframe));
7315 r_skinframe.loadsequence = 1;
7316 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7318 r_main_texturepool = R_AllocTexturePool();
7319 R_BuildBlankTextures();
7321 if (vid.support.arb_texture_cube_map)
7324 R_BuildNormalizationCube();
7326 r_texture_fogattenuation = NULL;
7327 r_texture_fogheighttexture = NULL;
7328 r_texture_gammaramps = NULL;
7329 //r_texture_fogintensity = NULL;
7330 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7331 memset(&r_waterstate, 0, sizeof(r_waterstate));
7332 r_glsl_permutation = NULL;
7333 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7334 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7335 glslshaderstring = NULL;
7337 r_cg_permutation = NULL;
7338 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7339 Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7340 cgshaderstring = NULL;
7343 r_hlsl_permutation = NULL;
7344 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7345 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7346 hlslshaderstring = NULL;
7348 memset(&r_svbsp, 0, sizeof (r_svbsp));
7350 r_refdef.fogmasktable_density = 0;
7353 void gl_main_shutdown(void)
7356 R_FrameData_Reset();
7358 R_Main_FreeViewCache();
7360 switch(vid.renderpath)
7362 case RENDERPATH_GL11:
7363 case RENDERPATH_GL13:
7364 case RENDERPATH_GL20:
7365 case RENDERPATH_CGGL:
7367 qglDeleteQueriesARB(r_maxqueries, r_queries);
7369 case RENDERPATH_D3D9:
7370 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7372 case RENDERPATH_D3D10:
7373 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7375 case RENDERPATH_D3D11:
7376 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7378 case RENDERPATH_SOFT:
7384 memset(r_queries, 0, sizeof(r_queries));
7386 r_qwskincache = NULL;
7387 r_qwskincache_size = 0;
7389 // clear out the r_skinframe state
7390 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7391 memset(&r_skinframe, 0, sizeof(r_skinframe));
7394 Mem_Free(r_svbsp.nodes);
7395 memset(&r_svbsp, 0, sizeof (r_svbsp));
7396 R_FreeTexturePool(&r_main_texturepool);
7397 loadingscreentexture = NULL;
7398 r_texture_blanknormalmap = NULL;
7399 r_texture_white = NULL;
7400 r_texture_grey128 = NULL;
7401 r_texture_black = NULL;
7402 r_texture_whitecube = NULL;
7403 r_texture_normalizationcube = NULL;
7404 r_texture_fogattenuation = NULL;
7405 r_texture_fogheighttexture = NULL;
7406 r_texture_gammaramps = NULL;
7407 r_texture_numcubemaps = 0;
7408 //r_texture_fogintensity = NULL;
7409 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7410 memset(&r_waterstate, 0, sizeof(r_waterstate));
7413 r_glsl_permutation = NULL;
7414 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7415 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
7416 glslshaderstring = NULL;
7418 r_cg_permutation = NULL;
7419 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7420 Mem_ExpandableArray_FreeArray(&r_cg_permutationarray);
7421 cgshaderstring = NULL;
7424 r_hlsl_permutation = NULL;
7425 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7426 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
7427 hlslshaderstring = NULL;
7431 extern void CL_ParseEntityLump(char *entitystring);
7432 void gl_main_newmap(void)
7434 // FIXME: move this code to client
7435 char *entities, entname[MAX_QPATH];
7437 Mem_Free(r_qwskincache);
7438 r_qwskincache = NULL;
7439 r_qwskincache_size = 0;
7442 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7443 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7445 CL_ParseEntityLump(entities);
7449 if (cl.worldmodel->brush.entities)
7450 CL_ParseEntityLump(cl.worldmodel->brush.entities);
7452 R_Main_FreeViewCache();
7454 R_FrameData_Reset();
7457 void GL_Main_Init(void)
7459 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7461 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7462 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7463 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7464 if (gamemode == GAME_NEHAHRA)
7466 Cvar_RegisterVariable (&gl_fogenable);
7467 Cvar_RegisterVariable (&gl_fogdensity);
7468 Cvar_RegisterVariable (&gl_fogred);
7469 Cvar_RegisterVariable (&gl_foggreen);
7470 Cvar_RegisterVariable (&gl_fogblue);
7471 Cvar_RegisterVariable (&gl_fogstart);
7472 Cvar_RegisterVariable (&gl_fogend);
7473 Cvar_RegisterVariable (&gl_skyclip);
7475 Cvar_RegisterVariable(&r_motionblur);
7476 Cvar_RegisterVariable(&r_motionblur_maxblur);
7477 Cvar_RegisterVariable(&r_motionblur_bmin);
7478 Cvar_RegisterVariable(&r_motionblur_vmin);
7479 Cvar_RegisterVariable(&r_motionblur_vmax);
7480 Cvar_RegisterVariable(&r_motionblur_vcoeff);
7481 Cvar_RegisterVariable(&r_motionblur_randomize);
7482 Cvar_RegisterVariable(&r_damageblur);
7483 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7484 Cvar_RegisterVariable(&r_equalize_entities_minambient);
7485 Cvar_RegisterVariable(&r_equalize_entities_by);
7486 Cvar_RegisterVariable(&r_equalize_entities_to);
7487 Cvar_RegisterVariable(&r_depthfirst);
7488 Cvar_RegisterVariable(&r_useinfinitefarclip);
7489 Cvar_RegisterVariable(&r_farclip_base);
7490 Cvar_RegisterVariable(&r_farclip_world);
7491 Cvar_RegisterVariable(&r_nearclip);
7492 Cvar_RegisterVariable(&r_showbboxes);
7493 Cvar_RegisterVariable(&r_showsurfaces);
7494 Cvar_RegisterVariable(&r_showtris);
7495 Cvar_RegisterVariable(&r_shownormals);
7496 Cvar_RegisterVariable(&r_showlighting);
7497 Cvar_RegisterVariable(&r_showshadowvolumes);
7498 Cvar_RegisterVariable(&r_showcollisionbrushes);
7499 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7500 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7501 Cvar_RegisterVariable(&r_showdisabledepthtest);
7502 Cvar_RegisterVariable(&r_drawportals);
7503 Cvar_RegisterVariable(&r_drawentities);
7504 Cvar_RegisterVariable(&r_draw2d);
7505 Cvar_RegisterVariable(&r_drawworld);
7506 Cvar_RegisterVariable(&r_cullentities_trace);
7507 Cvar_RegisterVariable(&r_cullentities_trace_samples);
7508 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7509 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7510 Cvar_RegisterVariable(&r_cullentities_trace_delay);
7511 Cvar_RegisterVariable(&r_drawviewmodel);
7512 Cvar_RegisterVariable(&r_drawexteriormodel);
7513 Cvar_RegisterVariable(&r_speeds);
7514 Cvar_RegisterVariable(&r_fullbrights);
7515 Cvar_RegisterVariable(&r_wateralpha);
7516 Cvar_RegisterVariable(&r_dynamic);
7517 Cvar_RegisterVariable(&r_fakelight);
7518 Cvar_RegisterVariable(&r_fakelight_intensity);
7519 Cvar_RegisterVariable(&r_fullbright);
7520 Cvar_RegisterVariable(&r_shadows);
7521 Cvar_RegisterVariable(&r_shadows_darken);
7522 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7523 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7524 Cvar_RegisterVariable(&r_shadows_throwdistance);
7525 Cvar_RegisterVariable(&r_shadows_throwdirection);
7526 Cvar_RegisterVariable(&r_shadows_focus);
7527 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7528 Cvar_RegisterVariable(&r_q1bsp_skymasking);
7529 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7530 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7531 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7532 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7533 Cvar_RegisterVariable(&r_fog_exp2);
7534 Cvar_RegisterVariable(&r_drawfog);
7535 Cvar_RegisterVariable(&r_transparentdepthmasking);
7536 Cvar_RegisterVariable(&r_texture_dds_load);
7537 Cvar_RegisterVariable(&r_texture_dds_save);
7538 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7539 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7540 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7541 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7542 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7543 Cvar_RegisterVariable(&r_textureunits);
7544 Cvar_RegisterVariable(&gl_combine);
7545 Cvar_RegisterVariable(&r_glsl);
7546 Cvar_RegisterVariable(&r_glsl_deluxemapping);
7547 Cvar_RegisterVariable(&r_glsl_offsetmapping);
7548 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7549 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7550 Cvar_RegisterVariable(&r_glsl_postprocess);
7551 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7552 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7553 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7554 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7555 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
7556 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
7557 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
7558 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
7560 Cvar_RegisterVariable(&r_water);
7561 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7562 Cvar_RegisterVariable(&r_water_clippingplanebias);
7563 Cvar_RegisterVariable(&r_water_refractdistort);
7564 Cvar_RegisterVariable(&r_water_reflectdistort);
7565 Cvar_RegisterVariable(&r_water_scissormode);
7566 Cvar_RegisterVariable(&r_lerpsprites);
7567 Cvar_RegisterVariable(&r_lerpmodels);
7568 Cvar_RegisterVariable(&r_lerplightstyles);
7569 Cvar_RegisterVariable(&r_waterscroll);
7570 Cvar_RegisterVariable(&r_bloom);
7571 Cvar_RegisterVariable(&r_bloom_colorscale);
7572 Cvar_RegisterVariable(&r_bloom_brighten);
7573 Cvar_RegisterVariable(&r_bloom_blur);
7574 Cvar_RegisterVariable(&r_bloom_resolution);
7575 Cvar_RegisterVariable(&r_bloom_colorexponent);
7576 Cvar_RegisterVariable(&r_bloom_colorsubtract);
7577 Cvar_RegisterVariable(&r_hdr);
7578 Cvar_RegisterVariable(&r_hdr_scenebrightness);
7579 Cvar_RegisterVariable(&r_hdr_glowintensity);
7580 Cvar_RegisterVariable(&r_hdr_range);
7581 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7582 Cvar_RegisterVariable(&developer_texturelogging);
7583 Cvar_RegisterVariable(&gl_lightmaps);
7584 Cvar_RegisterVariable(&r_test);
7585 Cvar_RegisterVariable(&r_glsl_saturation);
7586 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
7587 Cvar_RegisterVariable(&r_framedatasize);
7588 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7589 Cvar_SetValue("r_fullbrights", 0);
7590 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7592 Cvar_RegisterVariable(&r_track_sprites);
7593 Cvar_RegisterVariable(&r_track_sprites_flags);
7594 Cvar_RegisterVariable(&r_track_sprites_scalew);
7595 Cvar_RegisterVariable(&r_track_sprites_scaleh);
7596 Cvar_RegisterVariable(&r_overheadsprites_perspective);
7597 Cvar_RegisterVariable(&r_overheadsprites_pushback);
7598 Cvar_RegisterVariable(&r_overheadsprites_scalex);
7599 Cvar_RegisterVariable(&r_overheadsprites_scaley);
7602 extern void R_Textures_Init(void);
7603 extern void GL_Draw_Init(void);
7604 extern void GL_Main_Init(void);
7605 extern void R_Shadow_Init(void);
7606 extern void R_Sky_Init(void);
7607 extern void GL_Surf_Init(void);
7608 extern void R_Particles_Init(void);
7609 extern void R_Explosion_Init(void);
7610 extern void gl_backend_init(void);
7611 extern void Sbar_Init(void);
7612 extern void R_LightningBeams_Init(void);
7613 extern void Mod_RenderInit(void);
7614 extern void Font_Init(void);
7616 void Render_Init(void)
7629 R_LightningBeams_Init();
7638 extern char *ENGINE_EXTENSIONS;
7641 gl_renderer = (const char *)qglGetString(GL_RENDERER);
7642 gl_vendor = (const char *)qglGetString(GL_VENDOR);
7643 gl_version = (const char *)qglGetString(GL_VERSION);
7644 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7648 if (!gl_platformextensions)
7649 gl_platformextensions = "";
7651 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7652 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7653 Con_Printf("GL_VERSION: %s\n", gl_version);
7654 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7655 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7657 VID_CheckExtensions();
7659 // LordHavoc: report supported extensions
7660 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7662 // clear to black (loading plaque will be seen over this)
7663 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7666 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7670 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7672 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7675 p = r_refdef.view.frustum + i;
7680 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7684 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7688 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7692 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7696 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7700 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7704 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7708 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7716 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7720 for (i = 0;i < numplanes;i++)
7727 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7731 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7735 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7739 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7743 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7747 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7751 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7755 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7763 //==================================================================================
7765 // LordHavoc: this stores temporary data used within the same frame
7767 typedef struct r_framedata_mem_s
7769 struct r_framedata_mem_s *purge; // older mem block to free on next frame
7770 size_t size; // how much usable space
7771 size_t current; // how much space in use
7772 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
7773 size_t wantedsize; // how much space was allocated
7774 unsigned char *data; // start of real data (16byte aligned)
7778 static r_framedata_mem_t *r_framedata_mem;
7780 void R_FrameData_Reset(void)
7782 while (r_framedata_mem)
7784 r_framedata_mem_t *next = r_framedata_mem->purge;
7785 Mem_Free(r_framedata_mem);
7786 r_framedata_mem = next;
7790 void R_FrameData_Resize(void)
7793 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7794 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
7795 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
7797 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
7798 newmem->wantedsize = wantedsize;
7799 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
7800 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
7801 newmem->current = 0;
7803 newmem->purge = r_framedata_mem;
7804 r_framedata_mem = newmem;
7808 void R_FrameData_NewFrame(void)
7810 R_FrameData_Resize();
7811 if (!r_framedata_mem)
7813 // if we ran out of space on the last frame, free the old memory now
7814 while (r_framedata_mem->purge)
7816 // repeatedly remove the second item in the list, leaving only head
7817 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
7818 Mem_Free(r_framedata_mem->purge);
7819 r_framedata_mem->purge = next;
7821 // reset the current mem pointer
7822 r_framedata_mem->current = 0;
7823 r_framedata_mem->mark = 0;
7826 void *R_FrameData_Alloc(size_t size)
7830 // align to 16 byte boundary - the data pointer is already aligned, so we
7831 // only need to ensure the size of every allocation is also aligned
7832 size = (size + 15) & ~15;
7834 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
7836 // emergency - we ran out of space, allocate more memory
7837 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
7838 R_FrameData_Resize();
7841 data = r_framedata_mem->data + r_framedata_mem->current;
7842 r_framedata_mem->current += size;
7844 // count the usage for stats
7845 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
7846 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
7848 return (void *)data;
7851 void *R_FrameData_Store(size_t size, void *data)
7853 void *d = R_FrameData_Alloc(size);
7855 memcpy(d, data, size);
7859 void R_FrameData_SetMark(void)
7861 if (!r_framedata_mem)
7863 r_framedata_mem->mark = r_framedata_mem->current;
7866 void R_FrameData_ReturnToMark(void)
7868 if (!r_framedata_mem)
7870 r_framedata_mem->current = r_framedata_mem->mark;
7873 //==================================================================================
7875 // LordHavoc: animcache originally written by Echon, rewritten since then
7878 * Animation cache prevents re-generating mesh data for an animated model
7879 * multiple times in one frame for lighting, shadowing, reflections, etc.
7882 void R_AnimCache_Free(void)
7886 void R_AnimCache_ClearCache(void)
7889 entity_render_t *ent;
7891 for (i = 0;i < r_refdef.scene.numentities;i++)
7893 ent = r_refdef.scene.entities[i];
7894 ent->animcache_vertex3f = NULL;
7895 ent->animcache_normal3f = NULL;
7896 ent->animcache_svector3f = NULL;
7897 ent->animcache_tvector3f = NULL;
7898 ent->animcache_vertexmesh = NULL;
7899 ent->animcache_vertex3fbuffer = NULL;
7900 ent->animcache_vertexmeshbuffer = NULL;
7904 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7908 // check if we need the meshbuffers
7909 if (!vid.useinterleavedarrays)
7912 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7913 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7914 // TODO: upload vertex3f buffer?
7915 if (ent->animcache_vertexmesh)
7917 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7918 for (i = 0;i < numvertices;i++)
7919 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7920 if (ent->animcache_svector3f)
7921 for (i = 0;i < numvertices;i++)
7922 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7923 if (ent->animcache_tvector3f)
7924 for (i = 0;i < numvertices;i++)
7925 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7926 if (ent->animcache_normal3f)
7927 for (i = 0;i < numvertices;i++)
7928 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7929 // TODO: upload vertexmeshbuffer?
7933 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7935 dp_model_t *model = ent->model;
7937 // see if it's already cached this frame
7938 if (ent->animcache_vertex3f)
7940 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7941 if (wantnormals || wanttangents)
7943 if (ent->animcache_normal3f)
7944 wantnormals = false;
7945 if (ent->animcache_svector3f)
7946 wanttangents = false;
7947 if (wantnormals || wanttangents)
7949 numvertices = model->surfmesh.num_vertices;
7951 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7954 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7955 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7957 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7958 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7964 // see if this ent is worth caching
7965 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7967 // get some memory for this entity and generate mesh data
7968 numvertices = model->surfmesh.num_vertices;
7969 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7971 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7974 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7975 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7977 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7978 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7983 void R_AnimCache_CacheVisibleEntities(void)
7986 qboolean wantnormals = true;
7987 qboolean wanttangents = !r_showsurfaces.integer;
7989 switch(vid.renderpath)
7991 case RENDERPATH_GL20:
7992 case RENDERPATH_CGGL:
7993 case RENDERPATH_D3D9:
7994 case RENDERPATH_D3D10:
7995 case RENDERPATH_D3D11:
7997 case RENDERPATH_GL13:
7998 case RENDERPATH_GL11:
7999 wanttangents = false;
8001 case RENDERPATH_SOFT:
8005 if (r_shownormals.integer)
8006 wanttangents = wantnormals = true;
8008 // TODO: thread this
8009 // NOTE: R_PrepareRTLights() also caches entities
8011 for (i = 0;i < r_refdef.scene.numentities;i++)
8012 if (r_refdef.viewcache.entityvisible[i])
8013 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
8016 //==================================================================================
8018 static void R_View_UpdateEntityLighting (void)
8021 entity_render_t *ent;
8022 vec3_t tempdiffusenormal, avg;
8023 vec_t f, fa, fd, fdd;
8024 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
8026 for (i = 0;i < r_refdef.scene.numentities;i++)
8028 ent = r_refdef.scene.entities[i];
8030 // skip unseen models
8031 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
8035 if (ent->model && ent->model->brush.num_leafs)
8037 // TODO: use modellight for r_ambient settings on world?
8038 VectorSet(ent->modellight_ambient, 0, 0, 0);
8039 VectorSet(ent->modellight_diffuse, 0, 0, 0);
8040 VectorSet(ent->modellight_lightdir, 0, 0, 1);
8044 // fetch the lighting from the worldmodel data
8045 VectorClear(ent->modellight_ambient);
8046 VectorClear(ent->modellight_diffuse);
8047 VectorClear(tempdiffusenormal);
8048 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
8051 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8053 // complete lightning for lit sprites
8054 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
8055 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
8057 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
8058 org[2] = org[2] + r_overheadsprites_pushback.value;
8059 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, ent->modellight_lightdir, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
8062 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
8064 if(ent->flags & RENDER_EQUALIZE)
8066 // first fix up ambient lighting...
8067 if(r_equalize_entities_minambient.value > 0)
8069 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
8072 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
8073 if(fa < r_equalize_entities_minambient.value * fd)
8076 // fa'/fd' = minambient
8077 // fa'+0.25*fd' = fa+0.25*fd
8079 // fa' = fd' * minambient
8080 // fd'*(0.25+minambient) = fa+0.25*fd
8082 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
8083 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
8085 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
8086 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
8087 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
8088 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
8093 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
8095 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
8096 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
8100 // adjust brightness and saturation to target
8101 avg[0] = avg[1] = avg[2] = fa / f;
8102 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
8103 avg[0] = avg[1] = avg[2] = fd / f;
8104 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
8110 VectorSet(ent->modellight_ambient, 1, 1, 1);
8112 // move the light direction into modelspace coordinates for lighting code
8113 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
8114 if(VectorLength2(ent->modellight_lightdir) == 0)
8115 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
8116 VectorNormalize(ent->modellight_lightdir);
8120 #define MAX_LINEOFSIGHTTRACES 64
8122 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
8125 vec3_t boxmins, boxmaxs;
8128 dp_model_t *model = r_refdef.scene.worldmodel;
8130 if (!model || !model->brush.TraceLineOfSight)
8133 // expand the box a little
8134 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
8135 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
8136 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
8137 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
8138 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
8139 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
8141 // return true if eye is inside enlarged box
8142 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
8146 VectorCopy(eye, start);
8147 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
8148 if (model->brush.TraceLineOfSight(model, start, end))
8151 // try various random positions
8152 for (i = 0;i < numsamples;i++)
8154 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
8155 if (model->brush.TraceLineOfSight(model, start, end))
8163 static void R_View_UpdateEntityVisible (void)
8168 entity_render_t *ent;
8170 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8171 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8172 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
8173 : RENDER_EXTERIORMODEL;
8174 if (!r_drawviewmodel.integer)
8175 renderimask |= RENDER_VIEWMODEL;
8176 if (!r_drawexteriormodel.integer)
8177 renderimask |= RENDER_EXTERIORMODEL;
8178 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
8180 // worldmodel can check visibility
8181 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
8182 for (i = 0;i < r_refdef.scene.numentities;i++)
8184 ent = r_refdef.scene.entities[i];
8185 if (!(ent->flags & renderimask))
8186 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)))
8187 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))
8188 r_refdef.viewcache.entityvisible[i] = true;
8190 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
8191 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
8193 for (i = 0;i < r_refdef.scene.numentities;i++)
8195 ent = r_refdef.scene.entities[i];
8196 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
8198 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
8200 continue; // temp entities do pvs only
8201 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
8202 ent->last_trace_visibility = realtime;
8203 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
8204 r_refdef.viewcache.entityvisible[i] = 0;
8211 // no worldmodel or it can't check visibility
8212 for (i = 0;i < r_refdef.scene.numentities;i++)
8214 ent = r_refdef.scene.entities[i];
8215 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));
8220 /// only used if skyrendermasked, and normally returns false
8221 int R_DrawBrushModelsSky (void)
8224 entity_render_t *ent;
8227 for (i = 0;i < r_refdef.scene.numentities;i++)
8229 if (!r_refdef.viewcache.entityvisible[i])
8231 ent = r_refdef.scene.entities[i];
8232 if (!ent->model || !ent->model->DrawSky)
8234 ent->model->DrawSky(ent);
8240 static void R_DrawNoModel(entity_render_t *ent);
8241 static void R_DrawModels(void)
8244 entity_render_t *ent;
8246 for (i = 0;i < r_refdef.scene.numentities;i++)
8248 if (!r_refdef.viewcache.entityvisible[i])
8250 ent = r_refdef.scene.entities[i];
8251 r_refdef.stats.entities++;
8252 if (ent->model && ent->model->Draw != NULL)
8253 ent->model->Draw(ent);
8259 static void R_DrawModelsDepth(void)
8262 entity_render_t *ent;
8264 for (i = 0;i < r_refdef.scene.numentities;i++)
8266 if (!r_refdef.viewcache.entityvisible[i])
8268 ent = r_refdef.scene.entities[i];
8269 if (ent->model && ent->model->DrawDepth != NULL)
8270 ent->model->DrawDepth(ent);
8274 static void R_DrawModelsDebug(void)
8277 entity_render_t *ent;
8279 for (i = 0;i < r_refdef.scene.numentities;i++)
8281 if (!r_refdef.viewcache.entityvisible[i])
8283 ent = r_refdef.scene.entities[i];
8284 if (ent->model && ent->model->DrawDebug != NULL)
8285 ent->model->DrawDebug(ent);
8289 static void R_DrawModelsAddWaterPlanes(void)
8292 entity_render_t *ent;
8294 for (i = 0;i < r_refdef.scene.numentities;i++)
8296 if (!r_refdef.viewcache.entityvisible[i])
8298 ent = r_refdef.scene.entities[i];
8299 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
8300 ent->model->DrawAddWaterPlanes(ent);
8304 static void R_View_SetFrustum(const int *scissor)
8307 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
8308 vec3_t forward, left, up, origin, v;
8312 // flipped x coordinates (because x points left here)
8313 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8314 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8316 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
8317 switch(vid.renderpath)
8319 case RENDERPATH_D3D9:
8320 case RENDERPATH_D3D10:
8321 case RENDERPATH_D3D11:
8322 case RENDERPATH_SOFT:
8323 // non-flipped y coordinates
8324 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8325 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8327 case RENDERPATH_GL11:
8328 case RENDERPATH_GL13:
8329 case RENDERPATH_GL20:
8330 case RENDERPATH_CGGL:
8331 // non-flipped y coordinates
8332 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8333 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8338 // we can't trust r_refdef.view.forward and friends in reflected scenes
8339 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
8342 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
8343 r_refdef.view.frustum[0].normal[1] = 0 - 0;
8344 r_refdef.view.frustum[0].normal[2] = -1 - 0;
8345 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
8346 r_refdef.view.frustum[1].normal[1] = 0 + 0;
8347 r_refdef.view.frustum[1].normal[2] = -1 + 0;
8348 r_refdef.view.frustum[2].normal[0] = 0 - 0;
8349 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
8350 r_refdef.view.frustum[2].normal[2] = -1 - 0;
8351 r_refdef.view.frustum[3].normal[0] = 0 + 0;
8352 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
8353 r_refdef.view.frustum[3].normal[2] = -1 + 0;
8357 zNear = r_refdef.nearclip;
8358 nudge = 1.0 - 1.0 / (1<<23);
8359 r_refdef.view.frustum[4].normal[0] = 0 - 0;
8360 r_refdef.view.frustum[4].normal[1] = 0 - 0;
8361 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
8362 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
8363 r_refdef.view.frustum[5].normal[0] = 0 + 0;
8364 r_refdef.view.frustum[5].normal[1] = 0 + 0;
8365 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
8366 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
8372 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8373 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8374 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8375 r_refdef.view.frustum[0].dist = m[15] - m[12];
8377 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8378 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8379 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8380 r_refdef.view.frustum[1].dist = m[15] + m[12];
8382 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8383 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8384 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8385 r_refdef.view.frustum[2].dist = m[15] - m[13];
8387 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8388 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8389 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8390 r_refdef.view.frustum[3].dist = m[15] + m[13];
8392 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8393 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8394 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8395 r_refdef.view.frustum[4].dist = m[15] - m[14];
8397 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8398 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8399 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8400 r_refdef.view.frustum[5].dist = m[15] + m[14];
8403 if (r_refdef.view.useperspective)
8405 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8406 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]);
8407 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]);
8408 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]);
8409 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]);
8411 // then the normals from the corners relative to origin
8412 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
8413 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
8414 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
8415 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
8417 // in a NORMAL view, forward cross left == up
8418 // in a REFLECTED view, forward cross left == down
8419 // so our cross products above need to be adjusted for a left handed coordinate system
8420 CrossProduct(forward, left, v);
8421 if(DotProduct(v, up) < 0)
8423 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
8424 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
8425 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
8426 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
8429 // Leaving those out was a mistake, those were in the old code, and they
8430 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8431 // I couldn't reproduce it after adding those normalizations. --blub
8432 VectorNormalize(r_refdef.view.frustum[0].normal);
8433 VectorNormalize(r_refdef.view.frustum[1].normal);
8434 VectorNormalize(r_refdef.view.frustum[2].normal);
8435 VectorNormalize(r_refdef.view.frustum[3].normal);
8437 // make the corners absolute
8438 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
8439 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
8440 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
8441 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
8444 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8446 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8447 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8448 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8449 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8450 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8454 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8455 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8456 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8457 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8458 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8459 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8460 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8461 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8462 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8463 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8465 r_refdef.view.numfrustumplanes = 5;
8467 if (r_refdef.view.useclipplane)
8469 r_refdef.view.numfrustumplanes = 6;
8470 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8473 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8474 PlaneClassify(r_refdef.view.frustum + i);
8476 // LordHavoc: note to all quake engine coders, Quake had a special case
8477 // for 90 degrees which assumed a square view (wrong), so I removed it,
8478 // Quake2 has it disabled as well.
8480 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8481 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8482 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8483 //PlaneClassify(&frustum[0]);
8485 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8486 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8487 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8488 //PlaneClassify(&frustum[1]);
8490 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8491 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8492 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8493 //PlaneClassify(&frustum[2]);
8495 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8496 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8497 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8498 //PlaneClassify(&frustum[3]);
8501 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8502 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8503 //PlaneClassify(&frustum[4]);
8506 void R_View_UpdateWithScissor(const int *myscissor)
8508 R_Main_ResizeViewCache();
8509 R_View_SetFrustum(myscissor);
8510 R_View_WorldVisibility(r_refdef.view.useclipplane);
8511 R_View_UpdateEntityVisible();
8512 R_View_UpdateEntityLighting();
8515 void R_View_Update(void)
8517 R_Main_ResizeViewCache();
8518 R_View_SetFrustum(NULL);
8519 R_View_WorldVisibility(r_refdef.view.useclipplane);
8520 R_View_UpdateEntityVisible();
8521 R_View_UpdateEntityLighting();
8524 void R_SetupView(qboolean allowwaterclippingplane)
8526 const float *customclipplane = NULL;
8528 if (r_refdef.view.useclipplane && allowwaterclippingplane)
8530 // LordHavoc: couldn't figure out how to make this approach the
8531 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8532 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8533 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8534 dist = r_refdef.view.clipplane.dist;
8535 plane[0] = r_refdef.view.clipplane.normal[0];
8536 plane[1] = r_refdef.view.clipplane.normal[1];
8537 plane[2] = r_refdef.view.clipplane.normal[2];
8539 customclipplane = plane;
8542 if (!r_refdef.view.useperspective)
8543 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);
8544 else if (vid.stencil && r_useinfinitefarclip.integer)
8545 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);
8547 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);
8548 R_SetViewport(&r_refdef.view.viewport);
8551 void R_EntityMatrix(const matrix4x4_t *matrix)
8553 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8555 gl_modelmatrixchanged = false;
8556 gl_modelmatrix = *matrix;
8557 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8558 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8559 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8560 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8562 switch(vid.renderpath)
8564 case RENDERPATH_D3D9:
8566 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8567 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8570 case RENDERPATH_D3D10:
8571 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8573 case RENDERPATH_D3D11:
8574 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8576 case RENDERPATH_GL20:
8577 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8578 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8579 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8581 case RENDERPATH_CGGL:
8584 if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8585 if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8586 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8589 case RENDERPATH_GL13:
8590 case RENDERPATH_GL11:
8591 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8593 case RENDERPATH_SOFT:
8594 DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
8595 DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
8601 void R_ResetViewRendering2D(void)
8603 r_viewport_t viewport;
8606 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8607 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);
8608 R_SetViewport(&viewport);
8609 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8610 GL_Color(1, 1, 1, 1);
8611 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8612 GL_BlendFunc(GL_ONE, GL_ZERO);
8613 GL_AlphaTest(false);
8614 GL_ScissorTest(false);
8615 GL_DepthMask(false);
8616 GL_DepthRange(0, 1);
8617 GL_DepthTest(false);
8618 GL_DepthFunc(GL_LEQUAL);
8619 R_EntityMatrix(&identitymatrix);
8620 R_Mesh_ResetTextureState();
8621 GL_PolygonOffset(0, 0);
8622 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8623 switch(vid.renderpath)
8625 case RENDERPATH_GL11:
8626 case RENDERPATH_GL13:
8627 case RENDERPATH_GL20:
8628 case RENDERPATH_CGGL:
8629 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8631 case RENDERPATH_D3D9:
8632 case RENDERPATH_D3D10:
8633 case RENDERPATH_D3D11:
8634 case RENDERPATH_SOFT:
8637 GL_CullFace(GL_NONE);
8640 void R_ResetViewRendering3D(void)
8645 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8646 GL_Color(1, 1, 1, 1);
8647 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8648 GL_BlendFunc(GL_ONE, GL_ZERO);
8649 GL_AlphaTest(false);
8650 GL_ScissorTest(true);
8652 GL_DepthRange(0, 1);
8654 GL_DepthFunc(GL_LEQUAL);
8655 R_EntityMatrix(&identitymatrix);
8656 R_Mesh_ResetTextureState();
8657 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8658 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8659 switch(vid.renderpath)
8661 case RENDERPATH_GL11:
8662 case RENDERPATH_GL13:
8663 case RENDERPATH_GL20:
8664 case RENDERPATH_CGGL:
8665 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8667 case RENDERPATH_D3D9:
8668 case RENDERPATH_D3D10:
8669 case RENDERPATH_D3D11:
8670 case RENDERPATH_SOFT:
8673 GL_CullFace(r_refdef.view.cullface_back);
8678 R_RenderView_UpdateViewVectors
8681 static void R_RenderView_UpdateViewVectors(void)
8683 // break apart the view matrix into vectors for various purposes
8684 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8685 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8686 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8687 VectorNegate(r_refdef.view.left, r_refdef.view.right);
8688 // make an inverted copy of the view matrix for tracking sprites
8689 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8692 void R_RenderScene(void);
8693 void R_RenderWaterPlanes(void);
8695 static void R_Water_StartFrame(void)
8698 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8699 r_waterstate_waterplane_t *p;
8701 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8704 switch(vid.renderpath)
8706 case RENDERPATH_GL20:
8707 case RENDERPATH_CGGL:
8708 case RENDERPATH_D3D9:
8709 case RENDERPATH_D3D10:
8710 case RENDERPATH_D3D11:
8711 case RENDERPATH_SOFT:
8713 case RENDERPATH_GL13:
8714 case RENDERPATH_GL11:
8718 // set waterwidth and waterheight to the water resolution that will be
8719 // used (often less than the screen resolution for faster rendering)
8720 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8721 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8723 // calculate desired texture sizes
8724 // can't use water if the card does not support the texture size
8725 if (!r_water.integer || r_showsurfaces.integer)
8726 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8727 else if (vid.support.arb_texture_non_power_of_two)
8729 texturewidth = waterwidth;
8730 textureheight = waterheight;
8731 camerawidth = waterwidth;
8732 cameraheight = waterheight;
8736 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
8737 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
8738 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
8739 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
8742 // allocate textures as needed
8743 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8745 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8746 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8748 if (p->texture_refraction)
8749 R_FreeTexture(p->texture_refraction);
8750 p->texture_refraction = NULL;
8751 if (p->texture_reflection)
8752 R_FreeTexture(p->texture_reflection);
8753 p->texture_reflection = NULL;
8754 if (p->texture_camera)
8755 R_FreeTexture(p->texture_camera);
8756 p->texture_camera = NULL;
8758 memset(&r_waterstate, 0, sizeof(r_waterstate));
8759 r_waterstate.texturewidth = texturewidth;
8760 r_waterstate.textureheight = textureheight;
8761 r_waterstate.camerawidth = camerawidth;
8762 r_waterstate.cameraheight = cameraheight;
8765 if (r_waterstate.texturewidth)
8767 r_waterstate.enabled = true;
8769 // when doing a reduced render (HDR) we want to use a smaller area
8770 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8771 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8773 // set up variables that will be used in shader setup
8774 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8775 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8776 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8777 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8780 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8781 r_waterstate.numwaterplanes = 0;
8784 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8786 int triangleindex, planeindex;
8792 r_waterstate_waterplane_t *p;
8793 texture_t *t = R_GetCurrentTexture(surface->texture);
8795 // just use the first triangle with a valid normal for any decisions
8796 VectorClear(normal);
8797 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8799 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8800 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8801 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8802 TriangleNormal(vert[0], vert[1], vert[2], normal);
8803 if (VectorLength2(normal) >= 0.001)
8807 VectorCopy(normal, plane.normal);
8808 VectorNormalize(plane.normal);
8809 plane.dist = DotProduct(vert[0], plane.normal);
8810 PlaneClassify(&plane);
8811 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8813 // skip backfaces (except if nocullface is set)
8814 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8816 VectorNegate(plane.normal, plane.normal);
8818 PlaneClassify(&plane);
8822 // find a matching plane if there is one
8823 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8824 if(p->camera_entity == t->camera_entity)
8825 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8827 if (planeindex >= r_waterstate.maxwaterplanes)
8828 return; // nothing we can do, out of planes
8830 // if this triangle does not fit any known plane rendered this frame, add one
8831 if (planeindex >= r_waterstate.numwaterplanes)
8833 // store the new plane
8834 r_waterstate.numwaterplanes++;
8836 // clear materialflags and pvs
8837 p->materialflags = 0;
8838 p->pvsvalid = false;
8839 p->camera_entity = t->camera_entity;
8840 VectorCopy(surface->mins, p->mins);
8841 VectorCopy(surface->maxs, p->maxs);
8846 p->mins[0] = min(p->mins[0], surface->mins[0]);
8847 p->mins[1] = min(p->mins[1], surface->mins[1]);
8848 p->mins[2] = min(p->mins[2], surface->mins[2]);
8849 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8850 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8851 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8853 // merge this surface's materialflags into the waterplane
8854 p->materialflags |= t->currentmaterialflags;
8855 if(!(p->materialflags & MATERIALFLAG_CAMERA))
8857 // merge this surface's PVS into the waterplane
8858 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8859 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8860 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8862 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8868 static void R_Water_ProcessPlanes(void)
8871 r_refdef_view_t originalview;
8872 r_refdef_view_t myview;
8874 r_waterstate_waterplane_t *p;
8877 originalview = r_refdef.view;
8879 // make sure enough textures are allocated
8880 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8882 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8884 if (!p->texture_refraction)
8885 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);
8886 if (!p->texture_refraction)
8889 else if (p->materialflags & MATERIALFLAG_CAMERA)
8891 if (!p->texture_camera)
8892 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);
8893 if (!p->texture_camera)
8897 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8899 if (!p->texture_reflection)
8900 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);
8901 if (!p->texture_reflection)
8907 r_refdef.view = originalview;
8908 r_refdef.view.showdebug = false;
8909 r_refdef.view.width = r_waterstate.waterwidth;
8910 r_refdef.view.height = r_waterstate.waterheight;
8911 r_refdef.view.useclipplane = true;
8912 myview = r_refdef.view;
8913 r_waterstate.renderingscene = true;
8914 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8916 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8918 r_refdef.view = myview;
8919 if(r_water_scissormode.integer)
8922 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8923 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8926 // render reflected scene and copy into texture
8927 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8928 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8929 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8930 r_refdef.view.clipplane = p->plane;
8932 // reverse the cullface settings for this render
8933 r_refdef.view.cullface_front = GL_FRONT;
8934 r_refdef.view.cullface_back = GL_BACK;
8935 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8937 r_refdef.view.usecustompvs = true;
8939 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8941 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8944 R_ResetViewRendering3D();
8945 R_ClearScreen(r_refdef.fogenabled);
8946 if(r_water_scissormode.integer & 2)
8947 R_View_UpdateWithScissor(myscissor);
8950 if(r_water_scissormode.integer & 1)
8951 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8954 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);
8957 // render the normal view scene and copy into texture
8958 // (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)
8959 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8961 r_refdef.view = myview;
8962 if(r_water_scissormode.integer)
8965 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8966 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8969 r_waterstate.renderingrefraction = true;
8971 r_refdef.view.clipplane = p->plane;
8972 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8973 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8975 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8977 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8978 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8979 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8980 R_RenderView_UpdateViewVectors();
8981 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8983 r_refdef.view.usecustompvs = true;
8984 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);
8988 PlaneClassify(&r_refdef.view.clipplane);
8990 R_ResetViewRendering3D();
8991 R_ClearScreen(r_refdef.fogenabled);
8992 if(r_water_scissormode.integer & 2)
8993 R_View_UpdateWithScissor(myscissor);
8996 if(r_water_scissormode.integer & 1)
8997 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
9000 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);
9001 r_waterstate.renderingrefraction = false;
9003 else if (p->materialflags & MATERIALFLAG_CAMERA)
9005 r_refdef.view = myview;
9007 r_refdef.view.clipplane = p->plane;
9008 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
9009 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
9011 r_refdef.view.width = r_waterstate.camerawidth;
9012 r_refdef.view.height = r_waterstate.cameraheight;
9013 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
9014 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
9016 if(p->camera_entity)
9018 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
9019 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
9022 // note: all of the view is used for displaying... so
9023 // there is no use in scissoring
9025 // reverse the cullface settings for this render
9026 r_refdef.view.cullface_front = GL_FRONT;
9027 r_refdef.view.cullface_back = GL_BACK;
9028 // also reverse the view matrix
9029 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
9030 R_RenderView_UpdateViewVectors();
9031 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
9033 r_refdef.view.usecustompvs = true;
9034 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);
9037 // camera needs no clipplane
9038 r_refdef.view.useclipplane = false;
9040 PlaneClassify(&r_refdef.view.clipplane);
9042 R_ResetViewRendering3D();
9043 R_ClearScreen(r_refdef.fogenabled);
9047 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);
9048 r_waterstate.renderingrefraction = false;
9052 r_waterstate.renderingscene = false;
9053 r_refdef.view = originalview;
9054 R_ResetViewRendering3D();
9055 R_ClearScreen(r_refdef.fogenabled);
9059 r_refdef.view = originalview;
9060 r_waterstate.renderingscene = false;
9061 Cvar_SetValueQuick(&r_water, 0);
9062 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
9066 void R_Bloom_StartFrame(void)
9068 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
9070 switch(vid.renderpath)
9072 case RENDERPATH_GL20:
9073 case RENDERPATH_CGGL:
9074 case RENDERPATH_D3D9:
9075 case RENDERPATH_D3D10:
9076 case RENDERPATH_D3D11:
9077 case RENDERPATH_SOFT:
9079 case RENDERPATH_GL13:
9080 case RENDERPATH_GL11:
9084 // set bloomwidth and bloomheight to the bloom resolution that will be
9085 // used (often less than the screen resolution for faster rendering)
9086 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
9087 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
9088 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
9089 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
9090 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
9092 // calculate desired texture sizes
9093 if (vid.support.arb_texture_non_power_of_two)
9095 screentexturewidth = r_refdef.view.width;
9096 screentextureheight = r_refdef.view.height;
9097 bloomtexturewidth = r_bloomstate.bloomwidth;
9098 bloomtextureheight = r_bloomstate.bloomheight;
9102 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
9103 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
9104 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
9105 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
9108 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))
9110 Cvar_SetValueQuick(&r_hdr, 0);
9111 Cvar_SetValueQuick(&r_bloom, 0);
9112 Cvar_SetValueQuick(&r_motionblur, 0);
9113 Cvar_SetValueQuick(&r_damageblur, 0);
9116 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)))
9117 screentexturewidth = screentextureheight = 0;
9118 if (!r_hdr.integer && !r_bloom.integer)
9119 bloomtexturewidth = bloomtextureheight = 0;
9121 // allocate textures as needed
9122 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
9124 if (r_bloomstate.texture_screen)
9125 R_FreeTexture(r_bloomstate.texture_screen);
9126 r_bloomstate.texture_screen = NULL;
9127 r_bloomstate.screentexturewidth = screentexturewidth;
9128 r_bloomstate.screentextureheight = screentextureheight;
9129 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
9130 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);
9132 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
9134 if (r_bloomstate.texture_bloom)
9135 R_FreeTexture(r_bloomstate.texture_bloom);
9136 r_bloomstate.texture_bloom = NULL;
9137 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
9138 r_bloomstate.bloomtextureheight = bloomtextureheight;
9139 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
9140 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);
9143 // when doing a reduced render (HDR) we want to use a smaller area
9144 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
9145 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
9146 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
9147 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
9148 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
9150 // set up a texcoord array for the full resolution screen image
9151 // (we have to keep this around to copy back during final render)
9152 r_bloomstate.screentexcoord2f[0] = 0;
9153 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
9154 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
9155 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
9156 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
9157 r_bloomstate.screentexcoord2f[5] = 0;
9158 r_bloomstate.screentexcoord2f[6] = 0;
9159 r_bloomstate.screentexcoord2f[7] = 0;
9161 // set up a texcoord array for the reduced resolution bloom image
9162 // (which will be additive blended over the screen image)
9163 r_bloomstate.bloomtexcoord2f[0] = 0;
9164 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9165 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9166 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9167 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9168 r_bloomstate.bloomtexcoord2f[5] = 0;
9169 r_bloomstate.bloomtexcoord2f[6] = 0;
9170 r_bloomstate.bloomtexcoord2f[7] = 0;
9172 switch(vid.renderpath)
9174 case RENDERPATH_GL11:
9175 case RENDERPATH_GL13:
9176 case RENDERPATH_GL20:
9177 case RENDERPATH_CGGL:
9178 case RENDERPATH_SOFT:
9180 case RENDERPATH_D3D9:
9181 case RENDERPATH_D3D10:
9182 case RENDERPATH_D3D11:
9185 for (i = 0;i < 4;i++)
9187 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
9188 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
9189 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
9190 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
9196 if (r_hdr.integer || r_bloom.integer)
9198 r_bloomstate.enabled = true;
9199 r_bloomstate.hdr = r_hdr.integer != 0;
9202 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);
9205 void R_Bloom_CopyBloomTexture(float colorscale)
9207 r_refdef.stats.bloom++;
9209 // scale down screen texture to the bloom texture size
9211 R_SetViewport(&r_bloomstate.viewport);
9212 GL_BlendFunc(GL_ONE, GL_ZERO);
9213 GL_Color(colorscale, colorscale, colorscale, 1);
9214 // 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...
9215 switch(vid.renderpath)
9217 case RENDERPATH_GL11:
9218 case RENDERPATH_GL13:
9219 case RENDERPATH_GL20:
9220 case RENDERPATH_CGGL:
9221 case RENDERPATH_SOFT:
9222 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9224 case RENDERPATH_D3D9:
9225 case RENDERPATH_D3D10:
9226 case RENDERPATH_D3D11:
9227 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9230 // TODO: do boxfilter scale-down in shader?
9231 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9232 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9233 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9235 // we now have a bloom image in the framebuffer
9236 // copy it into the bloom image texture for later processing
9237 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);
9238 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9241 void R_Bloom_CopyHDRTexture(void)
9243 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);
9244 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9247 void R_Bloom_MakeTexture(void)
9250 float xoffset, yoffset, r, brighten;
9252 r_refdef.stats.bloom++;
9254 R_ResetViewRendering2D();
9256 // we have a bloom image in the framebuffer
9258 R_SetViewport(&r_bloomstate.viewport);
9260 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
9263 r = bound(0, r_bloom_colorexponent.value / x, 1);
9264 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9266 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
9267 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9268 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9269 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9271 // copy the vertically blurred bloom view to a texture
9272 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);
9273 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9276 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
9277 brighten = r_bloom_brighten.value;
9279 brighten *= r_hdr_range.value;
9280 brighten = sqrt(brighten);
9282 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
9283 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9285 for (dir = 0;dir < 2;dir++)
9287 // blend on at multiple vertical offsets to achieve a vertical blur
9288 // TODO: do offset blends using GLSL
9289 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
9290 GL_BlendFunc(GL_ONE, GL_ZERO);
9291 for (x = -range;x <= range;x++)
9293 if (!dir){xoffset = 0;yoffset = x;}
9294 else {xoffset = x;yoffset = 0;}
9295 xoffset /= (float)r_bloomstate.bloomtexturewidth;
9296 yoffset /= (float)r_bloomstate.bloomtextureheight;
9297 // compute a texcoord array with the specified x and y offset
9298 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
9299 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9300 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9301 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9302 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9303 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
9304 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
9305 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
9306 // this r value looks like a 'dot' particle, fading sharply to
9307 // black at the edges
9308 // (probably not realistic but looks good enough)
9309 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
9310 //r = brighten/(range*2+1);
9311 r = brighten / (range * 2 + 1);
9313 r *= (1 - x*x/(float)(range*range));
9314 GL_Color(r, r, r, 1);
9315 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
9316 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9317 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9318 GL_BlendFunc(GL_ONE, GL_ONE);
9321 // copy the vertically blurred bloom view to a texture
9322 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);
9323 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9327 void R_HDR_RenderBloomTexture(void)
9329 int oldwidth, oldheight;
9330 float oldcolorscale;
9331 qboolean oldwaterstate;
9333 oldwaterstate = r_waterstate.enabled;
9334 oldcolorscale = r_refdef.view.colorscale;
9335 oldwidth = r_refdef.view.width;
9336 oldheight = r_refdef.view.height;
9337 r_refdef.view.width = r_bloomstate.bloomwidth;
9338 r_refdef.view.height = r_bloomstate.bloomheight;
9340 if(r_hdr.integer < 2)
9341 r_waterstate.enabled = false;
9343 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
9344 // TODO: add exposure compensation features
9345 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
9347 r_refdef.view.showdebug = false;
9348 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
9350 R_ResetViewRendering3D();
9352 R_ClearScreen(r_refdef.fogenabled);
9353 if (r_timereport_active)
9354 R_TimeReport("HDRclear");
9357 if (r_timereport_active)
9358 R_TimeReport("visibility");
9360 // only do secondary renders with HDR if r_hdr is 2 or higher
9361 r_waterstate.numwaterplanes = 0;
9362 if (r_waterstate.enabled)
9363 R_RenderWaterPlanes();
9365 r_refdef.view.showdebug = true;
9367 r_waterstate.numwaterplanes = 0;
9369 R_ResetViewRendering2D();
9371 R_Bloom_CopyHDRTexture();
9372 R_Bloom_MakeTexture();
9374 // restore the view settings
9375 r_waterstate.enabled = oldwaterstate;
9376 r_refdef.view.width = oldwidth;
9377 r_refdef.view.height = oldheight;
9378 r_refdef.view.colorscale = oldcolorscale;
9380 R_ResetViewRendering3D();
9382 R_ClearScreen(r_refdef.fogenabled);
9383 if (r_timereport_active)
9384 R_TimeReport("viewclear");
9387 static void R_BlendView(void)
9389 unsigned int permutation;
9390 float uservecs[4][4];
9392 switch (vid.renderpath)
9394 case RENDERPATH_GL20:
9395 case RENDERPATH_CGGL:
9396 case RENDERPATH_D3D9:
9397 case RENDERPATH_D3D10:
9398 case RENDERPATH_D3D11:
9399 case RENDERPATH_SOFT:
9401 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
9402 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
9403 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
9404 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
9405 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
9407 if (r_bloomstate.texture_screen)
9409 // make sure the buffer is available
9410 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
9412 R_ResetViewRendering2D();
9414 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
9416 // declare variables
9418 static float avgspeed;
9420 speed = VectorLength(cl.movement_velocity);
9422 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
9423 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
9425 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
9426 speed = bound(0, speed, 1);
9427 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
9429 // calculate values into a standard alpha
9430 cl.motionbluralpha = 1 - exp(-
9432 (r_motionblur.value * speed / 80)
9434 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
9437 max(0.0001, cl.time - cl.oldtime) // fps independent
9440 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
9441 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
9443 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
9445 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9446 GL_Color(1, 1, 1, cl.motionbluralpha);
9447 switch(vid.renderpath)
9449 case RENDERPATH_GL11:
9450 case RENDERPATH_GL13:
9451 case RENDERPATH_GL20:
9452 case RENDERPATH_CGGL:
9453 case RENDERPATH_SOFT:
9454 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9456 case RENDERPATH_D3D9:
9457 case RENDERPATH_D3D10:
9458 case RENDERPATH_D3D11:
9459 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9462 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9463 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9464 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9468 // copy view into the screen texture
9469 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);
9470 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9472 else if (!r_bloomstate.texture_bloom)
9474 // we may still have to do view tint...
9475 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9477 // apply a color tint to the whole view
9478 R_ResetViewRendering2D();
9479 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9480 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9481 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9482 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9483 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9485 break; // no screen processing, no bloom, skip it
9488 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9490 // render simple bloom effect
9491 // copy the screen and shrink it and darken it for the bloom process
9492 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9493 // make the bloom texture
9494 R_Bloom_MakeTexture();
9497 #if _MSC_VER >= 1400
9498 #define sscanf sscanf_s
9500 memset(uservecs, 0, sizeof(uservecs));
9501 if (r_glsl_postprocess_uservec1_enable.integer)
9502 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9503 if (r_glsl_postprocess_uservec2_enable.integer)
9504 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9505 if (r_glsl_postprocess_uservec3_enable.integer)
9506 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9507 if (r_glsl_postprocess_uservec4_enable.integer)
9508 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9510 R_ResetViewRendering2D();
9511 GL_Color(1, 1, 1, 1);
9512 GL_BlendFunc(GL_ONE, GL_ZERO);
9514 switch(vid.renderpath)
9516 case RENDERPATH_GL20:
9517 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9518 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9519 if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
9520 if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
9521 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
9522 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]);
9523 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9524 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]);
9525 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]);
9526 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]);
9527 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]);
9528 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
9529 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9530 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);
9532 case RENDERPATH_CGGL:
9534 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9535 R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9536 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_bloomstate.texture_screen);CHECKCGERROR
9537 if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_bloomstate.texture_bloom );CHECKCGERROR
9538 if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps );CHECKCGERROR
9539 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
9540 if (r_cg_permutation->fp_PixelSize ) cgGLSetParameter2f( r_cg_permutation->fp_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9541 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
9542 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
9543 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
9544 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
9545 if (r_cg_permutation->fp_Saturation ) cgGLSetParameter1f( r_cg_permutation->fp_Saturation , r_glsl_saturation.value);CHECKCGERROR
9546 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9547 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);
9550 case RENDERPATH_D3D9:
9552 // 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...
9553 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9554 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9555 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
9556 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
9557 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
9558 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9559 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9560 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9561 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9562 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9563 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9564 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
9565 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9566 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9569 case RENDERPATH_D3D10:
9570 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9572 case RENDERPATH_D3D11:
9573 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9575 case RENDERPATH_SOFT:
9576 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9577 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
9578 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
9579 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
9580 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
9581 DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9582 DPSOFTRAST_Uniform2fARB(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9583 DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9584 DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9585 DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9586 DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9587 DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
9588 DPSOFTRAST_Uniform2fARB(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9589 DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9594 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9595 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9597 case RENDERPATH_GL13:
9598 case RENDERPATH_GL11:
9599 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9601 // apply a color tint to the whole view
9602 R_ResetViewRendering2D();
9603 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9604 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9605 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9606 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9607 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9613 matrix4x4_t r_waterscrollmatrix;
9615 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9617 if (r_refdef.fog_density)
9619 r_refdef.fogcolor[0] = r_refdef.fog_red;
9620 r_refdef.fogcolor[1] = r_refdef.fog_green;
9621 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9623 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9624 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9625 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9626 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9630 VectorCopy(r_refdef.fogcolor, fogvec);
9631 // color.rgb *= ContrastBoost * SceneBrightness;
9632 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9633 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9634 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9635 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9640 void R_UpdateVariables(void)
9644 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9646 r_refdef.farclip = r_farclip_base.value;
9647 if (r_refdef.scene.worldmodel)
9648 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9649 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9651 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9652 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9653 r_refdef.polygonfactor = 0;
9654 r_refdef.polygonoffset = 0;
9655 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9656 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9658 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9659 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9660 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
9661 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9662 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9663 if (FAKELIGHT_ENABLED)
9665 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
9667 if (r_showsurfaces.integer)
9669 r_refdef.scene.rtworld = false;
9670 r_refdef.scene.rtworldshadows = false;
9671 r_refdef.scene.rtdlight = false;
9672 r_refdef.scene.rtdlightshadows = false;
9673 r_refdef.lightmapintensity = 0;
9676 if (gamemode == GAME_NEHAHRA)
9678 if (gl_fogenable.integer)
9680 r_refdef.oldgl_fogenable = true;
9681 r_refdef.fog_density = gl_fogdensity.value;
9682 r_refdef.fog_red = gl_fogred.value;
9683 r_refdef.fog_green = gl_foggreen.value;
9684 r_refdef.fog_blue = gl_fogblue.value;
9685 r_refdef.fog_alpha = 1;
9686 r_refdef.fog_start = 0;
9687 r_refdef.fog_end = gl_skyclip.value;
9688 r_refdef.fog_height = 1<<30;
9689 r_refdef.fog_fadedepth = 128;
9691 else if (r_refdef.oldgl_fogenable)
9693 r_refdef.oldgl_fogenable = false;
9694 r_refdef.fog_density = 0;
9695 r_refdef.fog_red = 0;
9696 r_refdef.fog_green = 0;
9697 r_refdef.fog_blue = 0;
9698 r_refdef.fog_alpha = 0;
9699 r_refdef.fog_start = 0;
9700 r_refdef.fog_end = 0;
9701 r_refdef.fog_height = 1<<30;
9702 r_refdef.fog_fadedepth = 128;
9706 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9707 r_refdef.fog_start = max(0, r_refdef.fog_start);
9708 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9710 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9712 if (r_refdef.fog_density && r_drawfog.integer)
9714 r_refdef.fogenabled = true;
9715 // this is the point where the fog reaches 0.9986 alpha, which we
9716 // consider a good enough cutoff point for the texture
9717 // (0.9986 * 256 == 255.6)
9718 if (r_fog_exp2.integer)
9719 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9721 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9722 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9723 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9724 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9725 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9726 R_BuildFogHeightTexture();
9727 // fog color was already set
9728 // update the fog texture
9729 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)
9730 R_BuildFogTexture();
9731 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9732 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9735 r_refdef.fogenabled = false;
9737 switch(vid.renderpath)
9739 case RENDERPATH_GL20:
9740 case RENDERPATH_CGGL:
9741 case RENDERPATH_D3D9:
9742 case RENDERPATH_D3D10:
9743 case RENDERPATH_D3D11:
9744 case RENDERPATH_SOFT:
9745 if(v_glslgamma.integer && !vid_gammatables_trivial)
9747 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9749 // build GLSL gamma texture
9750 #define RAMPWIDTH 256
9751 unsigned short ramp[RAMPWIDTH * 3];
9752 unsigned char rampbgr[RAMPWIDTH][4];
9755 r_texture_gammaramps_serial = vid_gammatables_serial;
9757 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9758 for(i = 0; i < RAMPWIDTH; ++i)
9760 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9761 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9762 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9765 if (r_texture_gammaramps)
9767 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9771 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9777 // remove GLSL gamma texture
9780 case RENDERPATH_GL13:
9781 case RENDERPATH_GL11:
9786 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9787 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9793 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9794 if( scenetype != r_currentscenetype ) {
9795 // store the old scenetype
9796 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9797 r_currentscenetype = scenetype;
9798 // move in the new scene
9799 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9808 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9810 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9811 if( scenetype == r_currentscenetype ) {
9812 return &r_refdef.scene;
9814 return &r_scenes_store[ scenetype ];
9823 int dpsoftrast_test;
9824 void R_RenderView(void)
9826 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
9828 dpsoftrast_test = r_test.integer;
9830 if (r_timereport_active)
9831 R_TimeReport("start");
9832 r_textureframe++; // used only by R_GetCurrentTexture
9833 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9835 if(R_CompileShader_CheckStaticParms())
9838 if (!r_drawentities.integer)
9839 r_refdef.scene.numentities = 0;
9841 R_AnimCache_ClearCache();
9842 R_FrameData_NewFrame();
9844 /* adjust for stereo display */
9845 if(R_Stereo_Active())
9847 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);
9848 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
9851 if (r_refdef.view.isoverlay)
9853 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9854 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9855 R_TimeReport("depthclear");
9857 r_refdef.view.showdebug = false;
9859 r_waterstate.enabled = false;
9860 r_waterstate.numwaterplanes = 0;
9864 r_refdef.view.matrix = originalmatrix;
9870 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9872 r_refdef.view.matrix = originalmatrix;
9873 return; //Host_Error ("R_RenderView: NULL worldmodel");
9876 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9878 R_RenderView_UpdateViewVectors();
9880 R_Shadow_UpdateWorldLightSelection();
9882 R_Bloom_StartFrame();
9883 R_Water_StartFrame();
9886 if (r_timereport_active)
9887 R_TimeReport("viewsetup");
9889 R_ResetViewRendering3D();
9891 if (r_refdef.view.clear || r_refdef.fogenabled)
9893 R_ClearScreen(r_refdef.fogenabled);
9894 if (r_timereport_active)
9895 R_TimeReport("viewclear");
9897 r_refdef.view.clear = true;
9899 // this produces a bloom texture to be used in R_BlendView() later
9900 if (r_hdr.integer && r_bloomstate.bloomwidth)
9902 R_HDR_RenderBloomTexture();
9903 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9904 r_textureframe++; // used only by R_GetCurrentTexture
9907 r_refdef.view.showdebug = true;
9910 if (r_timereport_active)
9911 R_TimeReport("visibility");
9913 r_waterstate.numwaterplanes = 0;
9914 if (r_waterstate.enabled)
9915 R_RenderWaterPlanes();
9918 r_waterstate.numwaterplanes = 0;
9921 if (r_timereport_active)
9922 R_TimeReport("blendview");
9924 GL_Scissor(0, 0, vid.width, vid.height);
9925 GL_ScissorTest(false);
9927 r_refdef.view.matrix = originalmatrix;
9932 void R_RenderWaterPlanes(void)
9934 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9936 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9937 if (r_timereport_active)
9938 R_TimeReport("waterworld");
9941 // don't let sound skip if going slow
9942 if (r_refdef.scene.extraupdate)
9945 R_DrawModelsAddWaterPlanes();
9946 if (r_timereport_active)
9947 R_TimeReport("watermodels");
9949 if (r_waterstate.numwaterplanes)
9951 R_Water_ProcessPlanes();
9952 if (r_timereport_active)
9953 R_TimeReport("waterscenes");
9957 extern void R_DrawLightningBeams (void);
9958 extern void VM_CL_AddPolygonsToMeshQueue (void);
9959 extern void R_DrawPortals (void);
9960 extern cvar_t cl_locs_show;
9961 static void R_DrawLocs(void);
9962 static void R_DrawEntityBBoxes(void);
9963 static void R_DrawModelDecals(void);
9964 extern void R_DrawModelShadows(void);
9965 extern void R_DrawModelShadowMaps(void);
9966 extern cvar_t cl_decals_newsystem;
9967 extern qboolean r_shadow_usingdeferredprepass;
9968 void R_RenderScene(void)
9970 qboolean shadowmapping = false;
9972 if (r_timereport_active)
9973 R_TimeReport("beginscene");
9975 r_refdef.stats.renders++;
9979 // don't let sound skip if going slow
9980 if (r_refdef.scene.extraupdate)
9983 R_MeshQueue_BeginScene();
9987 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);
9989 if (r_timereport_active)
9990 R_TimeReport("skystartframe");
9992 if (cl.csqc_vidvars.drawworld)
9994 // don't let sound skip if going slow
9995 if (r_refdef.scene.extraupdate)
9998 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
10000 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
10001 if (r_timereport_active)
10002 R_TimeReport("worldsky");
10005 if (R_DrawBrushModelsSky() && r_timereport_active)
10006 R_TimeReport("bmodelsky");
10008 if (skyrendermasked && skyrenderlater)
10010 // we have to force off the water clipping plane while rendering sky
10011 R_SetupView(false);
10014 if (r_timereport_active)
10015 R_TimeReport("sky");
10019 R_AnimCache_CacheVisibleEntities();
10020 if (r_timereport_active)
10021 R_TimeReport("animation");
10023 R_Shadow_PrepareLights();
10024 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
10025 R_Shadow_PrepareModelShadows();
10026 if (r_timereport_active)
10027 R_TimeReport("preparelights");
10029 if (R_Shadow_ShadowMappingEnabled())
10030 shadowmapping = true;
10032 if (r_shadow_usingdeferredprepass)
10033 R_Shadow_DrawPrepass();
10035 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
10037 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
10038 if (r_timereport_active)
10039 R_TimeReport("worlddepth");
10041 if (r_depthfirst.integer >= 2)
10043 R_DrawModelsDepth();
10044 if (r_timereport_active)
10045 R_TimeReport("modeldepth");
10048 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
10050 R_DrawModelShadowMaps();
10051 R_ResetViewRendering3D();
10052 // don't let sound skip if going slow
10053 if (r_refdef.scene.extraupdate)
10057 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
10059 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
10060 if (r_timereport_active)
10061 R_TimeReport("world");
10064 // don't let sound skip if going slow
10065 if (r_refdef.scene.extraupdate)
10069 if (r_timereport_active)
10070 R_TimeReport("models");
10072 // don't let sound skip if going slow
10073 if (r_refdef.scene.extraupdate)
10076 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
10078 R_DrawModelShadows();
10079 R_ResetViewRendering3D();
10080 // don't let sound skip if going slow
10081 if (r_refdef.scene.extraupdate)
10085 if (!r_shadow_usingdeferredprepass)
10087 R_Shadow_DrawLights();
10088 if (r_timereport_active)
10089 R_TimeReport("rtlights");
10092 // don't let sound skip if going slow
10093 if (r_refdef.scene.extraupdate)
10096 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
10098 R_DrawModelShadows();
10099 R_ResetViewRendering3D();
10100 // don't let sound skip if going slow
10101 if (r_refdef.scene.extraupdate)
10105 if (cl.csqc_vidvars.drawworld)
10107 if (cl_decals_newsystem.integer)
10109 R_DrawModelDecals();
10110 if (r_timereport_active)
10111 R_TimeReport("modeldecals");
10116 if (r_timereport_active)
10117 R_TimeReport("decals");
10121 if (r_timereport_active)
10122 R_TimeReport("particles");
10124 R_DrawExplosions();
10125 if (r_timereport_active)
10126 R_TimeReport("explosions");
10128 R_DrawLightningBeams();
10129 if (r_timereport_active)
10130 R_TimeReport("lightning");
10133 VM_CL_AddPolygonsToMeshQueue();
10135 if (r_refdef.view.showdebug)
10137 if (cl_locs_show.integer)
10140 if (r_timereport_active)
10141 R_TimeReport("showlocs");
10144 if (r_drawportals.integer)
10147 if (r_timereport_active)
10148 R_TimeReport("portals");
10151 if (r_showbboxes.value > 0)
10153 R_DrawEntityBBoxes();
10154 if (r_timereport_active)
10155 R_TimeReport("bboxes");
10159 R_MeshQueue_RenderTransparent();
10160 if (r_timereport_active)
10161 R_TimeReport("drawtrans");
10163 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))
10165 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
10166 if (r_timereport_active)
10167 R_TimeReport("worlddebug");
10168 R_DrawModelsDebug();
10169 if (r_timereport_active)
10170 R_TimeReport("modeldebug");
10173 if (cl.csqc_vidvars.drawworld)
10175 R_Shadow_DrawCoronas();
10176 if (r_timereport_active)
10177 R_TimeReport("coronas");
10182 GL_DepthTest(false);
10183 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10184 GL_Color(1, 1, 1, 1);
10185 qglBegin(GL_POLYGON);
10186 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
10187 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
10188 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
10189 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
10191 qglBegin(GL_POLYGON);
10192 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]);
10193 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]);
10194 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]);
10195 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]);
10197 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10201 // don't let sound skip if going slow
10202 if (r_refdef.scene.extraupdate)
10205 R_ResetViewRendering2D();
10208 static const unsigned short bboxelements[36] =
10218 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
10221 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
10223 RSurf_ActiveWorldEntity();
10225 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10226 GL_DepthMask(false);
10227 GL_DepthRange(0, 1);
10228 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10229 // R_Mesh_ResetTextureState();
10231 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
10232 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
10233 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
10234 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
10235 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
10236 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
10237 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
10238 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
10239 R_FillColors(color4f, 8, cr, cg, cb, ca);
10240 if (r_refdef.fogenabled)
10242 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
10244 f1 = RSurf_FogVertex(v);
10246 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
10247 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
10248 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
10251 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
10252 R_Mesh_ResetTextureState();
10253 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10254 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
10257 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10261 prvm_edict_t *edict;
10262 prvm_prog_t *prog_save = prog;
10264 // this function draws bounding boxes of server entities
10268 GL_CullFace(GL_NONE);
10269 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10273 for (i = 0;i < numsurfaces;i++)
10275 edict = PRVM_EDICT_NUM(surfacelist[i]);
10276 switch ((int)edict->fields.server->solid)
10278 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
10279 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
10280 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
10281 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
10282 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
10283 default: Vector4Set(color, 0, 0, 0, 0.50);break;
10285 color[3] *= r_showbboxes.value;
10286 color[3] = bound(0, color[3], 1);
10287 GL_DepthTest(!r_showdisabledepthtest.integer);
10288 GL_CullFace(r_refdef.view.cullface_front);
10289 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
10295 static void R_DrawEntityBBoxes(void)
10298 prvm_edict_t *edict;
10300 prvm_prog_t *prog_save = prog;
10302 // this function draws bounding boxes of server entities
10308 for (i = 0;i < prog->num_edicts;i++)
10310 edict = PRVM_EDICT_NUM(i);
10311 if (edict->priv.server->free)
10313 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
10314 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
10316 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
10318 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
10319 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
10325 static const int nomodelelement3i[24] =
10337 static const unsigned short nomodelelement3s[24] =
10349 static const float nomodelvertex3f[6*3] =
10359 static const float nomodelcolor4f[6*4] =
10361 0.0f, 0.0f, 0.5f, 1.0f,
10362 0.0f, 0.0f, 0.5f, 1.0f,
10363 0.0f, 0.5f, 0.0f, 1.0f,
10364 0.0f, 0.5f, 0.0f, 1.0f,
10365 0.5f, 0.0f, 0.0f, 1.0f,
10366 0.5f, 0.0f, 0.0f, 1.0f
10369 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10373 float color4f[6*4];
10375 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);
10377 // this is only called once per entity so numsurfaces is always 1, and
10378 // surfacelist is always {0}, so this code does not handle batches
10380 if (rsurface.ent_flags & RENDER_ADDITIVE)
10382 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
10383 GL_DepthMask(false);
10385 else if (rsurface.colormod[3] < 1)
10387 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10388 GL_DepthMask(false);
10392 GL_BlendFunc(GL_ONE, GL_ZERO);
10393 GL_DepthMask(true);
10395 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
10396 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
10397 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
10398 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
10399 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
10400 for (i = 0, c = color4f;i < 6;i++, c += 4)
10402 c[0] *= rsurface.colormod[0];
10403 c[1] *= rsurface.colormod[1];
10404 c[2] *= rsurface.colormod[2];
10405 c[3] *= rsurface.colormod[3];
10407 if (r_refdef.fogenabled)
10409 for (i = 0, c = color4f;i < 6;i++, c += 4)
10411 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
10413 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
10414 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
10415 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
10418 // R_Mesh_ResetTextureState();
10419 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10420 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
10421 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
10424 void R_DrawNoModel(entity_render_t *ent)
10427 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
10428 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
10429 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
10431 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
10434 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
10436 vec3_t right1, right2, diff, normal;
10438 VectorSubtract (org2, org1, normal);
10440 // calculate 'right' vector for start
10441 VectorSubtract (r_refdef.view.origin, org1, diff);
10442 CrossProduct (normal, diff, right1);
10443 VectorNormalize (right1);
10445 // calculate 'right' vector for end
10446 VectorSubtract (r_refdef.view.origin, org2, diff);
10447 CrossProduct (normal, diff, right2);
10448 VectorNormalize (right2);
10450 vert[ 0] = org1[0] + width * right1[0];
10451 vert[ 1] = org1[1] + width * right1[1];
10452 vert[ 2] = org1[2] + width * right1[2];
10453 vert[ 3] = org1[0] - width * right1[0];
10454 vert[ 4] = org1[1] - width * right1[1];
10455 vert[ 5] = org1[2] - width * right1[2];
10456 vert[ 6] = org2[0] - width * right2[0];
10457 vert[ 7] = org2[1] - width * right2[1];
10458 vert[ 8] = org2[2] - width * right2[2];
10459 vert[ 9] = org2[0] + width * right2[0];
10460 vert[10] = org2[1] + width * right2[1];
10461 vert[11] = org2[2] + width * right2[2];
10464 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)
10466 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
10467 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
10468 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
10469 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
10470 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
10471 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
10472 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
10473 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
10474 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
10475 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
10476 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
10477 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
10480 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
10485 VectorSet(v, x, y, z);
10486 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
10487 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
10489 if (i == mesh->numvertices)
10491 if (mesh->numvertices < mesh->maxvertices)
10493 VectorCopy(v, vertex3f);
10494 mesh->numvertices++;
10496 return mesh->numvertices;
10502 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
10505 int *e, element[3];
10506 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10507 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10508 e = mesh->element3i + mesh->numtriangles * 3;
10509 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
10511 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
10512 if (mesh->numtriangles < mesh->maxtriangles)
10517 mesh->numtriangles++;
10519 element[1] = element[2];
10523 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
10526 int *e, element[3];
10527 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10528 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10529 e = mesh->element3i + mesh->numtriangles * 3;
10530 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10532 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10533 if (mesh->numtriangles < mesh->maxtriangles)
10538 mesh->numtriangles++;
10540 element[1] = element[2];
10544 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10545 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10547 int planenum, planenum2;
10550 mplane_t *plane, *plane2;
10552 double temppoints[2][256*3];
10553 // figure out how large a bounding box we need to properly compute this brush
10555 for (w = 0;w < numplanes;w++)
10556 maxdist = max(maxdist, fabs(planes[w].dist));
10557 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10558 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10559 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10563 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10564 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10566 if (planenum2 == planenum)
10568 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);
10571 if (tempnumpoints < 3)
10573 // generate elements forming a triangle fan for this polygon
10574 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10578 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)
10580 texturelayer_t *layer;
10581 layer = t->currentlayers + t->currentnumlayers++;
10582 layer->type = type;
10583 layer->depthmask = depthmask;
10584 layer->blendfunc1 = blendfunc1;
10585 layer->blendfunc2 = blendfunc2;
10586 layer->texture = texture;
10587 layer->texmatrix = *matrix;
10588 layer->color[0] = r;
10589 layer->color[1] = g;
10590 layer->color[2] = b;
10591 layer->color[3] = a;
10594 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10596 if(parms[0] == 0 && parms[1] == 0)
10598 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10599 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10604 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10607 index = parms[2] + r_refdef.scene.time * parms[3];
10608 index -= floor(index);
10609 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10612 case Q3WAVEFUNC_NONE:
10613 case Q3WAVEFUNC_NOISE:
10614 case Q3WAVEFUNC_COUNT:
10617 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10618 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10619 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10620 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10621 case Q3WAVEFUNC_TRIANGLE:
10623 f = index - floor(index);
10626 else if (index < 2)
10628 else if (index < 3)
10634 f = parms[0] + parms[1] * f;
10635 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10636 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10640 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10645 matrix4x4_t matrix, temp;
10646 switch(tcmod->tcmod)
10648 case Q3TCMOD_COUNT:
10650 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10651 matrix = r_waterscrollmatrix;
10653 matrix = identitymatrix;
10655 case Q3TCMOD_ENTITYTRANSLATE:
10656 // this is used in Q3 to allow the gamecode to control texcoord
10657 // scrolling on the entity, which is not supported in darkplaces yet.
10658 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10660 case Q3TCMOD_ROTATE:
10661 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10662 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10663 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10665 case Q3TCMOD_SCALE:
10666 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10668 case Q3TCMOD_SCROLL:
10669 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10671 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10672 w = (int) tcmod->parms[0];
10673 h = (int) tcmod->parms[1];
10674 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10676 idx = (int) floor(f * w * h);
10677 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10679 case Q3TCMOD_STRETCH:
10680 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10681 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10683 case Q3TCMOD_TRANSFORM:
10684 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
10685 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
10686 VectorSet(tcmat + 6, 0 , 0 , 1);
10687 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
10688 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10690 case Q3TCMOD_TURBULENT:
10691 // this is handled in the RSurf_PrepareVertices function
10692 matrix = identitymatrix;
10696 Matrix4x4_Concat(texmatrix, &matrix, &temp);
10699 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10701 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10702 char name[MAX_QPATH];
10703 skinframe_t *skinframe;
10704 unsigned char pixels[296*194];
10705 strlcpy(cache->name, skinname, sizeof(cache->name));
10706 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10707 if (developer_loading.integer)
10708 Con_Printf("loading %s\n", name);
10709 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10710 if (!skinframe || !skinframe->base)
10713 fs_offset_t filesize;
10715 f = FS_LoadFile(name, tempmempool, true, &filesize);
10718 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10719 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10723 cache->skinframe = skinframe;
10726 texture_t *R_GetCurrentTexture(texture_t *t)
10729 const entity_render_t *ent = rsurface.entity;
10730 dp_model_t *model = ent->model;
10731 q3shaderinfo_layer_tcmod_t *tcmod;
10733 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10734 return t->currentframe;
10735 t->update_lastrenderframe = r_textureframe;
10736 t->update_lastrenderentity = (void *)ent;
10738 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10739 t->camera_entity = ent->entitynumber;
10741 t->camera_entity = 0;
10743 // switch to an alternate material if this is a q1bsp animated material
10745 texture_t *texture = t;
10746 int s = rsurface.ent_skinnum;
10747 if ((unsigned int)s >= (unsigned int)model->numskins)
10749 if (model->skinscenes)
10751 if (model->skinscenes[s].framecount > 1)
10752 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10754 s = model->skinscenes[s].firstframe;
10757 t = t + s * model->num_surfaces;
10760 // use an alternate animation if the entity's frame is not 0,
10761 // and only if the texture has an alternate animation
10762 if (rsurface.ent_alttextures && t->anim_total[1])
10763 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10765 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10767 texture->currentframe = t;
10770 // update currentskinframe to be a qw skin or animation frame
10771 if (rsurface.ent_qwskin >= 0)
10773 i = rsurface.ent_qwskin;
10774 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10776 r_qwskincache_size = cl.maxclients;
10778 Mem_Free(r_qwskincache);
10779 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10781 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10782 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10783 t->currentskinframe = r_qwskincache[i].skinframe;
10784 if (t->currentskinframe == NULL)
10785 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10787 else if (t->numskinframes >= 2)
10788 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10789 if (t->backgroundnumskinframes >= 2)
10790 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10792 t->currentmaterialflags = t->basematerialflags;
10793 t->currentalpha = rsurface.colormod[3];
10794 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10795 t->currentalpha *= r_wateralpha.value;
10796 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10797 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10798 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10799 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10800 if (!(rsurface.ent_flags & RENDER_LIGHT))
10801 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10802 else if (FAKELIGHT_ENABLED)
10804 // no modellight if using fakelight for the map
10806 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10808 // pick a model lighting mode
10809 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10810 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10812 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10814 if (rsurface.ent_flags & RENDER_ADDITIVE)
10815 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10816 else if (t->currentalpha < 1)
10817 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10818 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10819 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10820 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10821 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10822 if (t->backgroundnumskinframes)
10823 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10824 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10826 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10827 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10830 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10831 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10832 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10834 // there is no tcmod
10835 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10837 t->currenttexmatrix = r_waterscrollmatrix;
10838 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10840 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10842 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10843 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10846 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10847 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10848 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10849 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10851 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10852 if (t->currentskinframe->qpixels)
10853 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10854 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10855 if (!t->basetexture)
10856 t->basetexture = r_texture_notexture;
10857 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10858 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10859 t->nmaptexture = t->currentskinframe->nmap;
10860 if (!t->nmaptexture)
10861 t->nmaptexture = r_texture_blanknormalmap;
10862 t->glosstexture = r_texture_black;
10863 t->glowtexture = t->currentskinframe->glow;
10864 t->fogtexture = t->currentskinframe->fog;
10865 t->reflectmasktexture = t->currentskinframe->reflect;
10866 if (t->backgroundnumskinframes)
10868 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10869 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10870 t->backgroundglosstexture = r_texture_black;
10871 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10872 if (!t->backgroundnmaptexture)
10873 t->backgroundnmaptexture = r_texture_blanknormalmap;
10877 t->backgroundbasetexture = r_texture_white;
10878 t->backgroundnmaptexture = r_texture_blanknormalmap;
10879 t->backgroundglosstexture = r_texture_black;
10880 t->backgroundglowtexture = NULL;
10882 t->specularpower = r_shadow_glossexponent.value;
10883 // TODO: store reference values for these in the texture?
10884 t->specularscale = 0;
10885 if (r_shadow_gloss.integer > 0)
10887 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10889 if (r_shadow_glossintensity.value > 0)
10891 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10892 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10893 t->specularscale = r_shadow_glossintensity.value;
10896 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10898 t->glosstexture = r_texture_white;
10899 t->backgroundglosstexture = r_texture_white;
10900 t->specularscale = r_shadow_gloss2intensity.value;
10901 t->specularpower = r_shadow_gloss2exponent.value;
10904 t->specularscale *= t->specularscalemod;
10905 t->specularpower *= t->specularpowermod;
10907 // lightmaps mode looks bad with dlights using actual texturing, so turn
10908 // off the colormap and glossmap, but leave the normalmap on as it still
10909 // accurately represents the shading involved
10910 if (gl_lightmaps.integer)
10912 t->basetexture = r_texture_grey128;
10913 t->pantstexture = r_texture_black;
10914 t->shirttexture = r_texture_black;
10915 t->nmaptexture = r_texture_blanknormalmap;
10916 t->glosstexture = r_texture_black;
10917 t->glowtexture = NULL;
10918 t->fogtexture = NULL;
10919 t->reflectmasktexture = NULL;
10920 t->backgroundbasetexture = NULL;
10921 t->backgroundnmaptexture = r_texture_blanknormalmap;
10922 t->backgroundglosstexture = r_texture_black;
10923 t->backgroundglowtexture = NULL;
10924 t->specularscale = 0;
10925 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10928 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10929 VectorClear(t->dlightcolor);
10930 t->currentnumlayers = 0;
10931 if (t->currentmaterialflags & MATERIALFLAG_WALL)
10933 int blendfunc1, blendfunc2;
10934 qboolean depthmask;
10935 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10937 blendfunc1 = GL_SRC_ALPHA;
10938 blendfunc2 = GL_ONE;
10940 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10942 blendfunc1 = GL_SRC_ALPHA;
10943 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10945 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10947 blendfunc1 = t->customblendfunc[0];
10948 blendfunc2 = t->customblendfunc[1];
10952 blendfunc1 = GL_ONE;
10953 blendfunc2 = GL_ZERO;
10955 // don't colormod evilblend textures
10956 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10957 VectorSet(t->lightmapcolor, 1, 1, 1);
10958 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10959 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10961 // fullbright is not affected by r_refdef.lightmapintensity
10962 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]);
10963 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10964 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]);
10965 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10966 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]);
10970 vec3_t ambientcolor;
10972 // set the color tint used for lights affecting this surface
10973 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10975 // q3bsp has no lightmap updates, so the lightstylevalue that
10976 // would normally be baked into the lightmap must be
10977 // applied to the color
10978 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10979 if (model->type == mod_brushq3)
10980 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10981 colorscale *= r_refdef.lightmapintensity;
10982 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10983 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10984 // basic lit geometry
10985 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]);
10986 // add pants/shirt if needed
10987 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10988 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]);
10989 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10990 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]);
10991 // now add ambient passes if needed
10992 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10994 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]);
10995 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10996 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]);
10997 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10998 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]);
11001 if (t->glowtexture != NULL && !gl_lightmaps.integer)
11002 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]);
11003 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
11005 // if this is opaque use alpha blend which will darken the earlier
11008 // if this is an alpha blended material, all the earlier passes
11009 // were darkened by fog already, so we only need to add the fog
11010 // color ontop through the fog mask texture
11012 // if this is an additive blended material, all the earlier passes
11013 // were darkened by fog already, and we should not add fog color
11014 // (because the background was not darkened, there is no fog color
11015 // that was lost behind it).
11016 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]);
11020 return t->currentframe;
11023 rsurfacestate_t rsurface;
11025 void RSurf_ActiveWorldEntity(void)
11027 dp_model_t *model = r_refdef.scene.worldmodel;
11028 //if (rsurface.entity == r_refdef.scene.worldentity)
11030 rsurface.entity = r_refdef.scene.worldentity;
11031 rsurface.skeleton = NULL;
11032 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
11033 rsurface.ent_skinnum = 0;
11034 rsurface.ent_qwskin = -1;
11035 rsurface.ent_shadertime = 0;
11036 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
11037 rsurface.matrix = identitymatrix;
11038 rsurface.inversematrix = identitymatrix;
11039 rsurface.matrixscale = 1;
11040 rsurface.inversematrixscale = 1;
11041 R_EntityMatrix(&identitymatrix);
11042 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
11043 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
11044 rsurface.fograngerecip = r_refdef.fograngerecip;
11045 rsurface.fogheightfade = r_refdef.fogheightfade;
11046 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
11047 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11048 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11049 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11050 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11051 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11052 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11053 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
11054 rsurface.colormod[3] = 1;
11055 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);
11056 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11057 rsurface.frameblend[0].lerp = 1;
11058 rsurface.ent_alttextures = false;
11059 rsurface.basepolygonfactor = r_refdef.polygonfactor;
11060 rsurface.basepolygonoffset = r_refdef.polygonoffset;
11061 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
11062 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11063 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
11064 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
11065 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11066 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
11067 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
11068 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11069 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
11070 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
11071 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11072 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
11073 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
11074 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11075 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11076 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
11077 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11078 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11079 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
11080 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11081 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11082 rsurface.modelelement3i = model->surfmesh.data_element3i;
11083 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11084 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11085 rsurface.modelelement3s = model->surfmesh.data_element3s;
11086 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11087 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11088 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11089 rsurface.modelnumvertices = model->surfmesh.num_vertices;
11090 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11091 rsurface.modelsurfaces = model->data_surfaces;
11092 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
11093 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
11094 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
11095 rsurface.modelgeneratedvertex = false;
11096 rsurface.batchgeneratedvertex = false;
11097 rsurface.batchfirstvertex = 0;
11098 rsurface.batchnumvertices = 0;
11099 rsurface.batchfirsttriangle = 0;
11100 rsurface.batchnumtriangles = 0;
11101 rsurface.batchvertex3f = NULL;
11102 rsurface.batchvertex3f_vertexbuffer = NULL;
11103 rsurface.batchvertex3f_bufferoffset = 0;
11104 rsurface.batchsvector3f = NULL;
11105 rsurface.batchsvector3f_vertexbuffer = NULL;
11106 rsurface.batchsvector3f_bufferoffset = 0;
11107 rsurface.batchtvector3f = NULL;
11108 rsurface.batchtvector3f_vertexbuffer = NULL;
11109 rsurface.batchtvector3f_bufferoffset = 0;
11110 rsurface.batchnormal3f = NULL;
11111 rsurface.batchnormal3f_vertexbuffer = NULL;
11112 rsurface.batchnormal3f_bufferoffset = 0;
11113 rsurface.batchlightmapcolor4f = NULL;
11114 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11115 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11116 rsurface.batchtexcoordtexture2f = NULL;
11117 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11118 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11119 rsurface.batchtexcoordlightmap2f = NULL;
11120 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11121 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11122 rsurface.batchvertexmesh = NULL;
11123 rsurface.batchvertexmeshbuffer = NULL;
11124 rsurface.batchvertex3fbuffer = NULL;
11125 rsurface.batchelement3i = NULL;
11126 rsurface.batchelement3i_indexbuffer = NULL;
11127 rsurface.batchelement3i_bufferoffset = 0;
11128 rsurface.batchelement3s = NULL;
11129 rsurface.batchelement3s_indexbuffer = NULL;
11130 rsurface.batchelement3s_bufferoffset = 0;
11131 rsurface.passcolor4f = NULL;
11132 rsurface.passcolor4f_vertexbuffer = NULL;
11133 rsurface.passcolor4f_bufferoffset = 0;
11136 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
11138 dp_model_t *model = ent->model;
11139 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
11141 rsurface.entity = (entity_render_t *)ent;
11142 rsurface.skeleton = ent->skeleton;
11143 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
11144 rsurface.ent_skinnum = ent->skinnum;
11145 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;
11146 rsurface.ent_shadertime = ent->shadertime;
11147 rsurface.ent_flags = ent->flags;
11148 rsurface.matrix = ent->matrix;
11149 rsurface.inversematrix = ent->inversematrix;
11150 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11151 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11152 R_EntityMatrix(&rsurface.matrix);
11153 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11154 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11155 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11156 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11157 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11158 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11159 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
11160 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
11161 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
11162 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
11163 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
11164 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
11165 rsurface.colormod[3] = ent->alpha;
11166 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
11167 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
11168 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
11169 rsurface.basepolygonfactor = r_refdef.polygonfactor;
11170 rsurface.basepolygonoffset = r_refdef.polygonoffset;
11171 if (ent->model->brush.submodel && !prepass)
11173 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
11174 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
11176 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
11178 if (ent->animcache_vertex3f)
11180 rsurface.modelvertex3f = ent->animcache_vertex3f;
11181 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
11182 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
11183 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
11184 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
11185 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
11186 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
11188 else if (wanttangents)
11190 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11191 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11192 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11193 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11194 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
11195 rsurface.modelvertexmesh = NULL;
11196 rsurface.modelvertexmeshbuffer = NULL;
11197 rsurface.modelvertex3fbuffer = NULL;
11199 else if (wantnormals)
11201 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11202 rsurface.modelsvector3f = NULL;
11203 rsurface.modeltvector3f = NULL;
11204 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11205 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
11206 rsurface.modelvertexmesh = NULL;
11207 rsurface.modelvertexmeshbuffer = NULL;
11208 rsurface.modelvertex3fbuffer = NULL;
11212 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11213 rsurface.modelsvector3f = NULL;
11214 rsurface.modeltvector3f = NULL;
11215 rsurface.modelnormal3f = NULL;
11216 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
11217 rsurface.modelvertexmesh = NULL;
11218 rsurface.modelvertexmeshbuffer = NULL;
11219 rsurface.modelvertex3fbuffer = NULL;
11221 rsurface.modelvertex3f_vertexbuffer = 0;
11222 rsurface.modelvertex3f_bufferoffset = 0;
11223 rsurface.modelsvector3f_vertexbuffer = 0;
11224 rsurface.modelsvector3f_bufferoffset = 0;
11225 rsurface.modeltvector3f_vertexbuffer = 0;
11226 rsurface.modeltvector3f_bufferoffset = 0;
11227 rsurface.modelnormal3f_vertexbuffer = 0;
11228 rsurface.modelnormal3f_bufferoffset = 0;
11229 rsurface.modelgeneratedvertex = true;
11233 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
11234 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11235 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
11236 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
11237 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11238 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
11239 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
11240 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11241 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
11242 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
11243 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11244 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
11245 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
11246 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
11247 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
11248 rsurface.modelgeneratedvertex = false;
11250 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
11251 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11252 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11253 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
11254 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11255 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11256 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
11257 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11258 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11259 rsurface.modelelement3i = model->surfmesh.data_element3i;
11260 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11261 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11262 rsurface.modelelement3s = model->surfmesh.data_element3s;
11263 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11264 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11265 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11266 rsurface.modelnumvertices = model->surfmesh.num_vertices;
11267 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11268 rsurface.modelsurfaces = model->data_surfaces;
11269 rsurface.batchgeneratedvertex = false;
11270 rsurface.batchfirstvertex = 0;
11271 rsurface.batchnumvertices = 0;
11272 rsurface.batchfirsttriangle = 0;
11273 rsurface.batchnumtriangles = 0;
11274 rsurface.batchvertex3f = NULL;
11275 rsurface.batchvertex3f_vertexbuffer = NULL;
11276 rsurface.batchvertex3f_bufferoffset = 0;
11277 rsurface.batchsvector3f = NULL;
11278 rsurface.batchsvector3f_vertexbuffer = NULL;
11279 rsurface.batchsvector3f_bufferoffset = 0;
11280 rsurface.batchtvector3f = NULL;
11281 rsurface.batchtvector3f_vertexbuffer = NULL;
11282 rsurface.batchtvector3f_bufferoffset = 0;
11283 rsurface.batchnormal3f = NULL;
11284 rsurface.batchnormal3f_vertexbuffer = NULL;
11285 rsurface.batchnormal3f_bufferoffset = 0;
11286 rsurface.batchlightmapcolor4f = NULL;
11287 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11288 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11289 rsurface.batchtexcoordtexture2f = NULL;
11290 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11291 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11292 rsurface.batchtexcoordlightmap2f = NULL;
11293 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11294 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11295 rsurface.batchvertexmesh = NULL;
11296 rsurface.batchvertexmeshbuffer = NULL;
11297 rsurface.batchvertex3fbuffer = NULL;
11298 rsurface.batchelement3i = NULL;
11299 rsurface.batchelement3i_indexbuffer = NULL;
11300 rsurface.batchelement3i_bufferoffset = 0;
11301 rsurface.batchelement3s = NULL;
11302 rsurface.batchelement3s_indexbuffer = NULL;
11303 rsurface.batchelement3s_bufferoffset = 0;
11304 rsurface.passcolor4f = NULL;
11305 rsurface.passcolor4f_vertexbuffer = NULL;
11306 rsurface.passcolor4f_bufferoffset = 0;
11309 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)
11311 rsurface.entity = r_refdef.scene.worldentity;
11312 rsurface.skeleton = NULL;
11313 rsurface.ent_skinnum = 0;
11314 rsurface.ent_qwskin = -1;
11315 rsurface.ent_shadertime = shadertime;
11316 rsurface.ent_flags = entflags;
11317 rsurface.modelnumvertices = numvertices;
11318 rsurface.modelnumtriangles = numtriangles;
11319 rsurface.matrix = *matrix;
11320 rsurface.inversematrix = *inversematrix;
11321 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11322 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11323 R_EntityMatrix(&rsurface.matrix);
11324 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11325 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11326 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11327 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11328 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11329 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11330 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11331 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11332 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11333 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11334 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11335 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
11336 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);
11337 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11338 rsurface.frameblend[0].lerp = 1;
11339 rsurface.ent_alttextures = false;
11340 rsurface.basepolygonfactor = r_refdef.polygonfactor;
11341 rsurface.basepolygonoffset = r_refdef.polygonoffset;
11344 rsurface.modelvertex3f = (float *)vertex3f;
11345 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11346 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11347 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11349 else if (wantnormals)
11351 rsurface.modelvertex3f = (float *)vertex3f;
11352 rsurface.modelsvector3f = NULL;
11353 rsurface.modeltvector3f = NULL;
11354 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11358 rsurface.modelvertex3f = (float *)vertex3f;
11359 rsurface.modelsvector3f = NULL;
11360 rsurface.modeltvector3f = NULL;
11361 rsurface.modelnormal3f = NULL;
11363 rsurface.modelvertexmesh = NULL;
11364 rsurface.modelvertexmeshbuffer = NULL;
11365 rsurface.modelvertex3fbuffer = NULL;
11366 rsurface.modelvertex3f_vertexbuffer = 0;
11367 rsurface.modelvertex3f_bufferoffset = 0;
11368 rsurface.modelsvector3f_vertexbuffer = 0;
11369 rsurface.modelsvector3f_bufferoffset = 0;
11370 rsurface.modeltvector3f_vertexbuffer = 0;
11371 rsurface.modeltvector3f_bufferoffset = 0;
11372 rsurface.modelnormal3f_vertexbuffer = 0;
11373 rsurface.modelnormal3f_bufferoffset = 0;
11374 rsurface.modelgeneratedvertex = true;
11375 rsurface.modellightmapcolor4f = (float *)color4f;
11376 rsurface.modellightmapcolor4f_vertexbuffer = 0;
11377 rsurface.modellightmapcolor4f_bufferoffset = 0;
11378 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
11379 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
11380 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
11381 rsurface.modeltexcoordlightmap2f = NULL;
11382 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
11383 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
11384 rsurface.modelelement3i = (int *)element3i;
11385 rsurface.modelelement3i_indexbuffer = NULL;
11386 rsurface.modelelement3i_bufferoffset = 0;
11387 rsurface.modelelement3s = (unsigned short *)element3s;
11388 rsurface.modelelement3s_indexbuffer = NULL;
11389 rsurface.modelelement3s_bufferoffset = 0;
11390 rsurface.modellightmapoffsets = NULL;
11391 rsurface.modelsurfaces = NULL;
11392 rsurface.batchgeneratedvertex = false;
11393 rsurface.batchfirstvertex = 0;
11394 rsurface.batchnumvertices = 0;
11395 rsurface.batchfirsttriangle = 0;
11396 rsurface.batchnumtriangles = 0;
11397 rsurface.batchvertex3f = NULL;
11398 rsurface.batchvertex3f_vertexbuffer = NULL;
11399 rsurface.batchvertex3f_bufferoffset = 0;
11400 rsurface.batchsvector3f = NULL;
11401 rsurface.batchsvector3f_vertexbuffer = NULL;
11402 rsurface.batchsvector3f_bufferoffset = 0;
11403 rsurface.batchtvector3f = NULL;
11404 rsurface.batchtvector3f_vertexbuffer = NULL;
11405 rsurface.batchtvector3f_bufferoffset = 0;
11406 rsurface.batchnormal3f = NULL;
11407 rsurface.batchnormal3f_vertexbuffer = NULL;
11408 rsurface.batchnormal3f_bufferoffset = 0;
11409 rsurface.batchlightmapcolor4f = NULL;
11410 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11411 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11412 rsurface.batchtexcoordtexture2f = NULL;
11413 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11414 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11415 rsurface.batchtexcoordlightmap2f = NULL;
11416 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11417 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11418 rsurface.batchvertexmesh = NULL;
11419 rsurface.batchvertexmeshbuffer = NULL;
11420 rsurface.batchvertex3fbuffer = NULL;
11421 rsurface.batchelement3i = NULL;
11422 rsurface.batchelement3i_indexbuffer = NULL;
11423 rsurface.batchelement3i_bufferoffset = 0;
11424 rsurface.batchelement3s = NULL;
11425 rsurface.batchelement3s_indexbuffer = NULL;
11426 rsurface.batchelement3s_bufferoffset = 0;
11427 rsurface.passcolor4f = NULL;
11428 rsurface.passcolor4f_vertexbuffer = NULL;
11429 rsurface.passcolor4f_bufferoffset = 0;
11431 if (rsurface.modelnumvertices && rsurface.modelelement3i)
11433 if ((wantnormals || wanttangents) && !normal3f)
11435 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11436 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
11438 if (wanttangents && !svector3f)
11440 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11441 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11442 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
11447 float RSurf_FogPoint(const float *v)
11449 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11450 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11451 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11452 float FogHeightFade = r_refdef.fogheightfade;
11454 unsigned int fogmasktableindex;
11455 if (r_refdef.fogplaneviewabove)
11456 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11458 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11459 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11460 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11463 float RSurf_FogVertex(const float *v)
11465 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11466 float FogPlaneViewDist = rsurface.fogplaneviewdist;
11467 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11468 float FogHeightFade = rsurface.fogheightfade;
11470 unsigned int fogmasktableindex;
11471 if (r_refdef.fogplaneviewabove)
11472 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11474 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11475 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11476 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11479 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11482 for (i = 0;i < numelements;i++)
11483 outelement3i[i] = inelement3i[i] + adjust;
11486 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11487 extern cvar_t gl_vbo;
11488 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11496 int surfacefirsttriangle;
11497 int surfacenumtriangles;
11498 int surfacefirstvertex;
11499 int surfaceendvertex;
11500 int surfacenumvertices;
11501 int batchnumvertices;
11502 int batchnumtriangles;
11506 qboolean dynamicvertex;
11510 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11511 float waveparms[4];
11512 q3shaderinfo_deform_t *deform;
11513 const msurface_t *surface, *firstsurface;
11514 r_vertexmesh_t *vertexmesh;
11515 if (!texturenumsurfaces)
11517 // find vertex range of this surface batch
11519 firstsurface = texturesurfacelist[0];
11520 firsttriangle = firstsurface->num_firsttriangle;
11521 batchnumvertices = 0;
11522 batchnumtriangles = 0;
11523 firstvertex = endvertex = firstsurface->num_firstvertex;
11524 for (i = 0;i < texturenumsurfaces;i++)
11526 surface = texturesurfacelist[i];
11527 if (surface != firstsurface + i)
11529 surfacefirstvertex = surface->num_firstvertex;
11530 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11531 surfacenumvertices = surface->num_vertices;
11532 surfacenumtriangles = surface->num_triangles;
11533 if (firstvertex > surfacefirstvertex)
11534 firstvertex = surfacefirstvertex;
11535 if (endvertex < surfaceendvertex)
11536 endvertex = surfaceendvertex;
11537 batchnumvertices += surfacenumvertices;
11538 batchnumtriangles += surfacenumtriangles;
11541 // we now know the vertex range used, and if there are any gaps in it
11542 rsurface.batchfirstvertex = firstvertex;
11543 rsurface.batchnumvertices = endvertex - firstvertex;
11544 rsurface.batchfirsttriangle = firsttriangle;
11545 rsurface.batchnumtriangles = batchnumtriangles;
11547 // this variable holds flags for which properties have been updated that
11548 // may require regenerating vertexmesh array...
11551 // check if any dynamic vertex processing must occur
11552 dynamicvertex = false;
11554 // if there is a chance of animated vertex colors, it's a dynamic batch
11555 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11557 dynamicvertex = true;
11558 batchneed |= BATCHNEED_NOGAPS;
11559 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
11562 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11564 switch (deform->deform)
11567 case Q3DEFORM_PROJECTIONSHADOW:
11568 case Q3DEFORM_TEXT0:
11569 case Q3DEFORM_TEXT1:
11570 case Q3DEFORM_TEXT2:
11571 case Q3DEFORM_TEXT3:
11572 case Q3DEFORM_TEXT4:
11573 case Q3DEFORM_TEXT5:
11574 case Q3DEFORM_TEXT6:
11575 case Q3DEFORM_TEXT7:
11576 case Q3DEFORM_NONE:
11578 case Q3DEFORM_AUTOSPRITE:
11579 dynamicvertex = true;
11580 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11581 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11583 case Q3DEFORM_AUTOSPRITE2:
11584 dynamicvertex = true;
11585 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11586 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11588 case Q3DEFORM_NORMAL:
11589 dynamicvertex = true;
11590 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11591 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11593 case Q3DEFORM_WAVE:
11594 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11595 break; // if wavefunc is a nop, ignore this transform
11596 dynamicvertex = true;
11597 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11598 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11600 case Q3DEFORM_BULGE:
11601 dynamicvertex = true;
11602 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11603 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11605 case Q3DEFORM_MOVE:
11606 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11607 break; // if wavefunc is a nop, ignore this transform
11608 dynamicvertex = true;
11609 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11610 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
11614 switch(rsurface.texture->tcgen.tcgen)
11617 case Q3TCGEN_TEXTURE:
11619 case Q3TCGEN_LIGHTMAP:
11620 dynamicvertex = true;
11621 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11622 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11624 case Q3TCGEN_VECTOR:
11625 dynamicvertex = true;
11626 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11627 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11629 case Q3TCGEN_ENVIRONMENT:
11630 dynamicvertex = true;
11631 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11632 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11635 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11637 dynamicvertex = true;
11638 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11639 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11642 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11644 dynamicvertex = true;
11645 batchneed |= BATCHNEED_NOGAPS;
11646 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11649 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11651 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11652 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
11653 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
11654 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
11655 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11656 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11657 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11660 // when the model data has no vertex buffer (dynamic mesh), we need to
11662 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
11663 batchneed |= BATCHNEED_NOGAPS;
11665 // if needsupdate, we have to do a dynamic vertex batch for sure
11666 if (needsupdate & batchneed)
11667 dynamicvertex = true;
11669 // see if we need to build vertexmesh from arrays
11670 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11671 dynamicvertex = true;
11673 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11674 // also some drivers strongly dislike firstvertex
11675 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11676 dynamicvertex = true;
11678 rsurface.batchvertex3f = rsurface.modelvertex3f;
11679 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11680 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11681 rsurface.batchsvector3f = rsurface.modelsvector3f;
11682 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11683 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11684 rsurface.batchtvector3f = rsurface.modeltvector3f;
11685 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11686 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11687 rsurface.batchnormal3f = rsurface.modelnormal3f;
11688 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11689 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11690 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11691 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
11692 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11693 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11694 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
11695 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
11696 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11697 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11698 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11699 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
11700 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11701 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11702 rsurface.batchelement3i = rsurface.modelelement3i;
11703 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11704 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11705 rsurface.batchelement3s = rsurface.modelelement3s;
11706 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11707 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11709 // if any dynamic vertex processing has to occur in software, we copy the
11710 // entire surface list together before processing to rebase the vertices
11711 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11713 // if any gaps exist and we do not have a static vertex buffer, we have to
11714 // copy the surface list together to avoid wasting upload bandwidth on the
11715 // vertices in the gaps.
11717 // if gaps exist and we have a static vertex buffer, we still have to
11718 // combine the index buffer ranges into one dynamic index buffer.
11720 // in all cases we end up with data that can be drawn in one call.
11722 if (!dynamicvertex)
11724 // static vertex data, just set pointers...
11725 rsurface.batchgeneratedvertex = false;
11726 // if there are gaps, we want to build a combined index buffer,
11727 // otherwise use the original static buffer with an appropriate offset
11730 // build a new triangle elements array for this batch
11731 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11732 rsurface.batchfirsttriangle = 0;
11734 for (i = 0;i < texturenumsurfaces;i++)
11736 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11737 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11738 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11739 numtriangles += surfacenumtriangles;
11741 rsurface.batchelement3i_indexbuffer = NULL;
11742 rsurface.batchelement3i_bufferoffset = 0;
11743 rsurface.batchelement3s = NULL;
11744 rsurface.batchelement3s_indexbuffer = NULL;
11745 rsurface.batchelement3s_bufferoffset = 0;
11746 if (endvertex <= 65536)
11748 // make a 16bit (unsigned short) index array if possible
11749 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11750 for (i = 0;i < numtriangles*3;i++)
11751 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11757 // something needs software processing, do it for real...
11758 // we only directly handle separate array data in this case and then
11759 // generate interleaved data if needed...
11760 rsurface.batchgeneratedvertex = true;
11762 // now copy the vertex data into a combined array and make an index array
11763 // (this is what Quake3 does all the time)
11764 //if (gaps || rsurface.batchfirstvertex)
11766 rsurface.batchvertex3fbuffer = NULL;
11767 rsurface.batchvertexmesh = NULL;
11768 rsurface.batchvertexmeshbuffer = NULL;
11769 rsurface.batchvertex3f = NULL;
11770 rsurface.batchvertex3f_vertexbuffer = NULL;
11771 rsurface.batchvertex3f_bufferoffset = 0;
11772 rsurface.batchsvector3f = NULL;
11773 rsurface.batchsvector3f_vertexbuffer = NULL;
11774 rsurface.batchsvector3f_bufferoffset = 0;
11775 rsurface.batchtvector3f = NULL;
11776 rsurface.batchtvector3f_vertexbuffer = NULL;
11777 rsurface.batchtvector3f_bufferoffset = 0;
11778 rsurface.batchnormal3f = NULL;
11779 rsurface.batchnormal3f_vertexbuffer = NULL;
11780 rsurface.batchnormal3f_bufferoffset = 0;
11781 rsurface.batchlightmapcolor4f = NULL;
11782 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11783 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11784 rsurface.batchtexcoordtexture2f = NULL;
11785 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11786 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11787 rsurface.batchtexcoordlightmap2f = NULL;
11788 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11789 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11790 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11791 rsurface.batchelement3i_indexbuffer = NULL;
11792 rsurface.batchelement3i_bufferoffset = 0;
11793 rsurface.batchelement3s = NULL;
11794 rsurface.batchelement3s_indexbuffer = NULL;
11795 rsurface.batchelement3s_bufferoffset = 0;
11796 // we'll only be setting up certain arrays as needed
11797 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11798 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
11799 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11800 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11801 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11802 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11803 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11805 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11806 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11808 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11809 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11810 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11811 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11812 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11813 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11816 for (i = 0;i < texturenumsurfaces;i++)
11818 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11819 surfacenumvertices = texturesurfacelist[i]->num_vertices;
11820 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11821 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11822 // copy only the data requested
11823 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11824 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11825 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11827 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11828 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11829 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11830 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11831 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11833 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11834 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11836 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11837 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11838 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11839 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11840 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11841 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11843 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11844 numvertices += surfacenumvertices;
11845 numtriangles += surfacenumtriangles;
11848 // generate a 16bit index array as well if possible
11849 // (in general, dynamic batches fit)
11850 if (numvertices <= 65536)
11852 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11853 for (i = 0;i < numtriangles*3;i++)
11854 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11857 // since we've copied everything, the batch now starts at 0
11858 rsurface.batchfirstvertex = 0;
11859 rsurface.batchnumvertices = batchnumvertices;
11860 rsurface.batchfirsttriangle = 0;
11861 rsurface.batchnumtriangles = batchnumtriangles;
11864 // q1bsp surfaces rendered in vertex color mode have to have colors
11865 // calculated based on lightstyles
11866 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11868 // generate color arrays for the surfaces in this list
11872 const int *offsets;
11873 const unsigned char *lm;
11874 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11875 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11876 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11878 for (i = 0;i < texturenumsurfaces;i++)
11880 surface = texturesurfacelist[i];
11881 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11882 surfacenumvertices = surface->num_vertices;
11883 if (surface->lightmapinfo->samples)
11885 for (j = 0;j < surfacenumvertices;j++)
11887 lm = surface->lightmapinfo->samples + offsets[j];
11888 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11889 VectorScale(lm, scale, c);
11890 if (surface->lightmapinfo->styles[1] != 255)
11892 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11894 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11895 VectorMA(c, scale, lm, c);
11896 if (surface->lightmapinfo->styles[2] != 255)
11899 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11900 VectorMA(c, scale, lm, c);
11901 if (surface->lightmapinfo->styles[3] != 255)
11904 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11905 VectorMA(c, scale, lm, c);
11912 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);
11918 for (j = 0;j < surfacenumvertices;j++)
11920 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11927 // if vertices are deformed (sprite flares and things in maps, possibly
11928 // water waves, bulges and other deformations), modify the copied vertices
11930 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11932 switch (deform->deform)
11935 case Q3DEFORM_PROJECTIONSHADOW:
11936 case Q3DEFORM_TEXT0:
11937 case Q3DEFORM_TEXT1:
11938 case Q3DEFORM_TEXT2:
11939 case Q3DEFORM_TEXT3:
11940 case Q3DEFORM_TEXT4:
11941 case Q3DEFORM_TEXT5:
11942 case Q3DEFORM_TEXT6:
11943 case Q3DEFORM_TEXT7:
11944 case Q3DEFORM_NONE:
11946 case Q3DEFORM_AUTOSPRITE:
11947 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11948 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11949 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11950 VectorNormalize(newforward);
11951 VectorNormalize(newright);
11952 VectorNormalize(newup);
11953 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11954 // rsurface.batchvertex3f_vertexbuffer = NULL;
11955 // rsurface.batchvertex3f_bufferoffset = 0;
11956 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
11957 // rsurface.batchsvector3f_vertexbuffer = NULL;
11958 // rsurface.batchsvector3f_bufferoffset = 0;
11959 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
11960 // rsurface.batchtvector3f_vertexbuffer = NULL;
11961 // rsurface.batchtvector3f_bufferoffset = 0;
11962 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11963 // rsurface.batchnormal3f_vertexbuffer = NULL;
11964 // rsurface.batchnormal3f_bufferoffset = 0;
11965 // a single autosprite surface can contain multiple sprites...
11966 for (j = 0;j < batchnumvertices - 3;j += 4)
11968 VectorClear(center);
11969 for (i = 0;i < 4;i++)
11970 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11971 VectorScale(center, 0.25f, center);
11972 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11973 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11974 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11975 for (i = 0;i < 4;i++)
11977 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11978 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
11981 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11982 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11983 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);
11985 case Q3DEFORM_AUTOSPRITE2:
11986 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11987 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11988 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11989 VectorNormalize(newforward);
11990 VectorNormalize(newright);
11991 VectorNormalize(newup);
11992 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11993 // rsurface.batchvertex3f_vertexbuffer = NULL;
11994 // rsurface.batchvertex3f_bufferoffset = 0;
11996 const float *v1, *v2;
12006 memset(shortest, 0, sizeof(shortest));
12007 // a single autosprite surface can contain multiple sprites...
12008 for (j = 0;j < batchnumvertices - 3;j += 4)
12010 VectorClear(center);
12011 for (i = 0;i < 4;i++)
12012 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
12013 VectorScale(center, 0.25f, center);
12014 // find the two shortest edges, then use them to define the
12015 // axis vectors for rotating around the central axis
12016 for (i = 0;i < 6;i++)
12018 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
12019 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
12020 l = VectorDistance2(v1, v2);
12021 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
12022 if (v1[2] != v2[2])
12023 l += (1.0f / 1024.0f);
12024 if (shortest[0].length2 > l || i == 0)
12026 shortest[1] = shortest[0];
12027 shortest[0].length2 = l;
12028 shortest[0].v1 = v1;
12029 shortest[0].v2 = v2;
12031 else if (shortest[1].length2 > l || i == 1)
12033 shortest[1].length2 = l;
12034 shortest[1].v1 = v1;
12035 shortest[1].v2 = v2;
12038 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
12039 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
12040 // this calculates the right vector from the shortest edge
12041 // and the up vector from the edge midpoints
12042 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
12043 VectorNormalize(right);
12044 VectorSubtract(end, start, up);
12045 VectorNormalize(up);
12046 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
12047 VectorSubtract(rsurface.localvieworigin, center, forward);
12048 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
12049 VectorNegate(forward, forward);
12050 VectorReflect(forward, 0, up, forward);
12051 VectorNormalize(forward);
12052 CrossProduct(up, forward, newright);
12053 VectorNormalize(newright);
12054 // rotate the quad around the up axis vector, this is made
12055 // especially easy by the fact we know the quad is flat,
12056 // so we only have to subtract the center position and
12057 // measure distance along the right vector, and then
12058 // multiply that by the newright vector and add back the
12060 // we also need to subtract the old position to undo the
12061 // displacement from the center, which we do with a
12062 // DotProduct, the subtraction/addition of center is also
12063 // optimized into DotProducts here
12064 l = DotProduct(right, center);
12065 for (i = 0;i < 4;i++)
12067 v1 = rsurface.batchvertex3f + 3*(j+i);
12068 f = DotProduct(right, v1) - l;
12069 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
12073 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
12075 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12076 // rsurface.batchnormal3f_vertexbuffer = NULL;
12077 // rsurface.batchnormal3f_bufferoffset = 0;
12078 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12080 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12082 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12083 // rsurface.batchsvector3f_vertexbuffer = NULL;
12084 // rsurface.batchsvector3f_bufferoffset = 0;
12085 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12086 // rsurface.batchtvector3f_vertexbuffer = NULL;
12087 // rsurface.batchtvector3f_bufferoffset = 0;
12088 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);
12091 case Q3DEFORM_NORMAL:
12092 // deform the normals to make reflections wavey
12093 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
12094 rsurface.batchnormal3f_vertexbuffer = NULL;
12095 rsurface.batchnormal3f_bufferoffset = 0;
12096 for (j = 0;j < batchnumvertices;j++)
12099 float *normal = rsurface.batchnormal3f + 3*j;
12100 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
12101 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
12102 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]);
12103 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]);
12104 VectorNormalize(normal);
12106 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12108 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12109 // rsurface.batchsvector3f_vertexbuffer = NULL;
12110 // rsurface.batchsvector3f_bufferoffset = 0;
12111 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12112 // rsurface.batchtvector3f_vertexbuffer = NULL;
12113 // rsurface.batchtvector3f_bufferoffset = 0;
12114 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);
12117 case Q3DEFORM_WAVE:
12118 // deform vertex array to make wavey water and flags and such
12119 waveparms[0] = deform->waveparms[0];
12120 waveparms[1] = deform->waveparms[1];
12121 waveparms[2] = deform->waveparms[2];
12122 waveparms[3] = deform->waveparms[3];
12123 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
12124 break; // if wavefunc is a nop, don't make a dynamic vertex array
12125 // this is how a divisor of vertex influence on deformation
12126 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
12127 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
12128 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
12129 // rsurface.batchvertex3f_vertexbuffer = NULL;
12130 // rsurface.batchvertex3f_bufferoffset = 0;
12131 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
12132 // rsurface.batchnormal3f_vertexbuffer = NULL;
12133 // rsurface.batchnormal3f_bufferoffset = 0;
12134 for (j = 0;j < batchnumvertices;j++)
12136 // if the wavefunc depends on time, evaluate it per-vertex
12139 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
12140 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
12142 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
12144 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12145 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12146 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12148 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12149 // rsurface.batchsvector3f_vertexbuffer = NULL;
12150 // rsurface.batchsvector3f_bufferoffset = 0;
12151 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12152 // rsurface.batchtvector3f_vertexbuffer = NULL;
12153 // rsurface.batchtvector3f_bufferoffset = 0;
12154 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);
12157 case Q3DEFORM_BULGE:
12158 // deform vertex array to make the surface have moving bulges
12159 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
12160 // rsurface.batchvertex3f_vertexbuffer = NULL;
12161 // rsurface.batchvertex3f_bufferoffset = 0;
12162 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
12163 // rsurface.batchnormal3f_vertexbuffer = NULL;
12164 // rsurface.batchnormal3f_bufferoffset = 0;
12165 for (j = 0;j < batchnumvertices;j++)
12167 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
12168 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
12170 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12171 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12172 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12174 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12175 // rsurface.batchsvector3f_vertexbuffer = NULL;
12176 // rsurface.batchsvector3f_bufferoffset = 0;
12177 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12178 // rsurface.batchtvector3f_vertexbuffer = NULL;
12179 // rsurface.batchtvector3f_bufferoffset = 0;
12180 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);
12183 case Q3DEFORM_MOVE:
12184 // deform vertex array
12185 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
12186 break; // if wavefunc is a nop, don't make a dynamic vertex array
12187 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
12188 VectorScale(deform->parms, scale, waveparms);
12189 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
12190 // rsurface.batchvertex3f_vertexbuffer = NULL;
12191 // rsurface.batchvertex3f_bufferoffset = 0;
12192 for (j = 0;j < batchnumvertices;j++)
12193 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
12198 // generate texcoords based on the chosen texcoord source
12199 switch(rsurface.texture->tcgen.tcgen)
12202 case Q3TCGEN_TEXTURE:
12204 case Q3TCGEN_LIGHTMAP:
12205 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12206 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12207 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12208 if (rsurface.batchtexcoordlightmap2f)
12209 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
12211 case Q3TCGEN_VECTOR:
12212 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12213 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12214 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12215 for (j = 0;j < batchnumvertices;j++)
12217 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
12218 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
12221 case Q3TCGEN_ENVIRONMENT:
12222 // make environment reflections using a spheremap
12223 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12224 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12225 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12226 for (j = 0;j < batchnumvertices;j++)
12228 // identical to Q3A's method, but executed in worldspace so
12229 // carried models can be shiny too
12231 float viewer[3], d, reflected[3], worldreflected[3];
12233 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
12234 // VectorNormalize(viewer);
12236 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
12238 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
12239 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
12240 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
12241 // note: this is proportinal to viewer, so we can normalize later
12243 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
12244 VectorNormalize(worldreflected);
12246 // note: this sphere map only uses world x and z!
12247 // so positive and negative y will LOOK THE SAME.
12248 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
12249 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
12253 // the only tcmod that needs software vertex processing is turbulent, so
12254 // check for it here and apply the changes if needed
12255 // and we only support that as the first one
12256 // (handling a mixture of turbulent and other tcmods would be problematic
12257 // without punting it entirely to a software path)
12258 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
12260 amplitude = rsurface.texture->tcmods[0].parms[1];
12261 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
12262 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12263 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12264 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12265 for (j = 0;j < batchnumvertices;j++)
12267 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);
12268 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12272 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
12274 // convert the modified arrays to vertex structs
12275 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
12276 // rsurface.batchvertexmeshbuffer = NULL;
12277 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
12278 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12279 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
12280 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
12281 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12282 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
12283 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
12285 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12287 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
12288 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
12291 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
12292 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12293 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
12294 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
12295 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12296 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
12297 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
12298 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12299 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
12303 void RSurf_DrawBatch(void)
12305 // sometimes a zero triangle surface (usually a degenerate patch) makes it
12306 // through the pipeline, killing it earlier in the pipeline would have
12307 // per-surface overhead rather than per-batch overhead, so it's best to
12308 // reject it here, before it hits glDraw.
12309 if (rsurface.batchnumtriangles == 0)
12312 // batch debugging code
12313 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
12319 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
12320 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
12323 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
12325 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
12327 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
12328 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);
12335 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);
12338 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
12340 // pick the closest matching water plane
12341 int planeindex, vertexindex, bestplaneindex = -1;
12345 r_waterstate_waterplane_t *p;
12346 qboolean prepared = false;
12348 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
12350 if(p->camera_entity != rsurface.texture->camera_entity)
12355 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12357 if(rsurface.batchnumvertices == 0)
12360 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
12362 Matrix4x4_Transform(&rsurface.matrix, v, vert);
12363 d += fabs(PlaneDiff(vert, &p->plane));
12365 if (bestd > d || bestplaneindex < 0)
12368 bestplaneindex = planeindex;
12371 return bestplaneindex;
12372 // NOTE: this MAY return a totally unrelated water plane; we can ignore
12373 // this situation though, as it might be better to render single larger
12374 // batches with useless stuff (backface culled for example) than to
12375 // render multiple smaller batches
12378 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
12381 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12382 rsurface.passcolor4f_vertexbuffer = 0;
12383 rsurface.passcolor4f_bufferoffset = 0;
12384 for (i = 0;i < rsurface.batchnumvertices;i++)
12385 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
12388 static void RSurf_DrawBatch_GL11_ApplyFog(void)
12395 if (rsurface.passcolor4f)
12397 // generate color arrays
12398 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
12399 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12400 rsurface.passcolor4f_vertexbuffer = 0;
12401 rsurface.passcolor4f_bufferoffset = 0;
12402 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)
12404 f = RSurf_FogVertex(v);
12413 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12414 rsurface.passcolor4f_vertexbuffer = 0;
12415 rsurface.passcolor4f_bufferoffset = 0;
12416 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
12418 f = RSurf_FogVertex(v);
12427 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
12434 if (!rsurface.passcolor4f)
12436 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
12437 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12438 rsurface.passcolor4f_vertexbuffer = 0;
12439 rsurface.passcolor4f_bufferoffset = 0;
12440 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
12442 f = RSurf_FogVertex(v);
12443 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
12444 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
12445 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
12450 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
12455 if (!rsurface.passcolor4f)
12457 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
12458 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12459 rsurface.passcolor4f_vertexbuffer = 0;
12460 rsurface.passcolor4f_bufferoffset = 0;
12461 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12470 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12475 if (!rsurface.passcolor4f)
12477 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
12478 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12479 rsurface.passcolor4f_vertexbuffer = 0;
12480 rsurface.passcolor4f_bufferoffset = 0;
12481 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12483 c2[0] = c[0] + r_refdef.scene.ambient;
12484 c2[1] = c[1] + r_refdef.scene.ambient;
12485 c2[2] = c[2] + r_refdef.scene.ambient;
12490 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12493 rsurface.passcolor4f = NULL;
12494 rsurface.passcolor4f_vertexbuffer = 0;
12495 rsurface.passcolor4f_bufferoffset = 0;
12496 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12497 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12498 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12499 GL_Color(r, g, b, a);
12500 R_Mesh_TexBind(0, rsurface.lightmaptexture);
12504 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12506 // TODO: optimize applyfog && applycolor case
12507 // just apply fog if necessary, and tint the fog color array if necessary
12508 rsurface.passcolor4f = NULL;
12509 rsurface.passcolor4f_vertexbuffer = 0;
12510 rsurface.passcolor4f_bufferoffset = 0;
12511 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12512 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12513 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12514 GL_Color(r, g, b, a);
12518 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12521 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12522 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12523 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12524 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12525 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12526 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12527 GL_Color(r, g, b, a);
12531 static void RSurf_DrawBatch_GL11_ClampColor(void)
12536 if (!rsurface.passcolor4f)
12538 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12540 c2[0] = bound(0.0f, c1[0], 1.0f);
12541 c2[1] = bound(0.0f, c1[1], 1.0f);
12542 c2[2] = bound(0.0f, c1[2], 1.0f);
12543 c2[3] = bound(0.0f, c1[3], 1.0f);
12547 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
12557 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12558 rsurface.passcolor4f_vertexbuffer = 0;
12559 rsurface.passcolor4f_bufferoffset = 0;
12560 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)
12562 f = -DotProduct(r_refdef.view.forward, n);
12564 f = f * 0.85 + 0.15; // work around so stuff won't get black
12565 f *= r_refdef.lightmapintensity;
12566 Vector4Set(c, f, f, f, 1);
12570 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12572 RSurf_DrawBatch_GL11_ApplyFakeLight();
12573 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12574 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12575 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12576 GL_Color(r, g, b, a);
12580 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12588 vec3_t ambientcolor;
12589 vec3_t diffusecolor;
12593 VectorCopy(rsurface.modellight_lightdir, lightdir);
12594 f = 0.5f * r_refdef.lightmapintensity;
12595 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12596 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12597 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12598 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12599 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12600 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12602 if (VectorLength2(diffusecolor) > 0)
12604 // q3-style directional shading
12605 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12606 rsurface.passcolor4f_vertexbuffer = 0;
12607 rsurface.passcolor4f_bufferoffset = 0;
12608 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)
12610 if ((f = DotProduct(n, lightdir)) > 0)
12611 VectorMA(ambientcolor, f, diffusecolor, c);
12613 VectorCopy(ambientcolor, c);
12620 *applycolor = false;
12624 *r = ambientcolor[0];
12625 *g = ambientcolor[1];
12626 *b = ambientcolor[2];
12627 rsurface.passcolor4f = NULL;
12628 rsurface.passcolor4f_vertexbuffer = 0;
12629 rsurface.passcolor4f_bufferoffset = 0;
12633 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12635 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12636 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12637 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12638 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12639 GL_Color(r, g, b, a);
12643 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12649 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12651 f = 1 - RSurf_FogVertex(v);
12659 void RSurf_SetupDepthAndCulling(void)
12661 // submodels are biased to avoid z-fighting with world surfaces that they
12662 // may be exactly overlapping (avoids z-fighting artifacts on certain
12663 // doors and things in Quake maps)
12664 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12665 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12666 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12667 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12670 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12672 // transparent sky would be ridiculous
12673 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12675 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12676 skyrenderlater = true;
12677 RSurf_SetupDepthAndCulling();
12678 GL_DepthMask(true);
12679 // LordHavoc: HalfLife maps have freaky skypolys so don't use
12680 // skymasking on them, and Quake3 never did sky masking (unlike
12681 // software Quake and software Quake2), so disable the sky masking
12682 // in Quake3 maps as it causes problems with q3map2 sky tricks,
12683 // and skymasking also looks very bad when noclipping outside the
12684 // level, so don't use it then either.
12685 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12687 R_Mesh_ResetTextureState();
12688 if (skyrendermasked)
12690 R_SetupShader_DepthOrShadow();
12691 // depth-only (masking)
12692 GL_ColorMask(0,0,0,0);
12693 // just to make sure that braindead drivers don't draw
12694 // anything despite that colormask...
12695 GL_BlendFunc(GL_ZERO, GL_ONE);
12696 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12697 if (rsurface.batchvertex3fbuffer)
12698 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12700 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12704 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12706 GL_BlendFunc(GL_ONE, GL_ZERO);
12707 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12708 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12709 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12712 if (skyrendermasked)
12713 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12715 R_Mesh_ResetTextureState();
12716 GL_Color(1, 1, 1, 1);
12719 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12720 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12721 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12723 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12727 // render screenspace normalmap to texture
12728 GL_DepthMask(true);
12729 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12734 // bind lightmap texture
12736 // water/refraction/reflection/camera surfaces have to be handled specially
12737 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
12739 int start, end, startplaneindex;
12740 for (start = 0;start < texturenumsurfaces;start = end)
12742 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12743 if(startplaneindex < 0)
12745 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
12746 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
12750 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12752 // now that we have a batch using the same planeindex, render it
12753 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
12755 // render water or distortion background
12756 GL_DepthMask(true);
12757 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));
12759 // blend surface on top
12760 GL_DepthMask(false);
12761 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12764 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
12766 // render surface with reflection texture as input
12767 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12768 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));
12775 // render surface batch normally
12776 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12777 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12781 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12783 // OpenGL 1.3 path - anything not completely ancient
12784 qboolean applycolor;
12787 const texturelayer_t *layer;
12788 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);
12789 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12791 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12794 int layertexrgbscale;
12795 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12797 if (layerindex == 0)
12798 GL_AlphaTest(true);
12801 GL_AlphaTest(false);
12802 GL_DepthFunc(GL_EQUAL);
12805 GL_DepthMask(layer->depthmask && writedepth);
12806 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12807 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12809 layertexrgbscale = 4;
12810 VectorScale(layer->color, 0.25f, layercolor);
12812 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12814 layertexrgbscale = 2;
12815 VectorScale(layer->color, 0.5f, layercolor);
12819 layertexrgbscale = 1;
12820 VectorScale(layer->color, 1.0f, layercolor);
12822 layercolor[3] = layer->color[3];
12823 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12824 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12825 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12826 switch (layer->type)
12828 case TEXTURELAYERTYPE_LITTEXTURE:
12829 // single-pass lightmapped texture with 2x rgbscale
12830 R_Mesh_TexBind(0, r_texture_white);
12831 R_Mesh_TexMatrix(0, NULL);
12832 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12833 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12834 R_Mesh_TexBind(1, layer->texture);
12835 R_Mesh_TexMatrix(1, &layer->texmatrix);
12836 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12837 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12838 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12839 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12840 else if (FAKELIGHT_ENABLED)
12841 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12842 else if (rsurface.uselightmaptexture)
12843 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12845 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12847 case TEXTURELAYERTYPE_TEXTURE:
12848 // singletexture unlit texture with transparency support
12849 R_Mesh_TexBind(0, layer->texture);
12850 R_Mesh_TexMatrix(0, &layer->texmatrix);
12851 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12852 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12853 R_Mesh_TexBind(1, 0);
12854 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12855 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12857 case TEXTURELAYERTYPE_FOG:
12858 // singletexture fogging
12859 if (layer->texture)
12861 R_Mesh_TexBind(0, layer->texture);
12862 R_Mesh_TexMatrix(0, &layer->texmatrix);
12863 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12864 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12868 R_Mesh_TexBind(0, 0);
12869 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12871 R_Mesh_TexBind(1, 0);
12872 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12873 // generate a color array for the fog pass
12874 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12875 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12879 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12882 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12884 GL_DepthFunc(GL_LEQUAL);
12885 GL_AlphaTest(false);
12889 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12891 // OpenGL 1.1 - crusty old voodoo path
12894 const texturelayer_t *layer;
12895 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);
12896 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12898 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12900 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12902 if (layerindex == 0)
12903 GL_AlphaTest(true);
12906 GL_AlphaTest(false);
12907 GL_DepthFunc(GL_EQUAL);
12910 GL_DepthMask(layer->depthmask && writedepth);
12911 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12912 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12913 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12914 switch (layer->type)
12916 case TEXTURELAYERTYPE_LITTEXTURE:
12917 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12919 // two-pass lit texture with 2x rgbscale
12920 // first the lightmap pass
12921 R_Mesh_TexBind(0, r_texture_white);
12922 R_Mesh_TexMatrix(0, NULL);
12923 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12924 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12925 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12926 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12927 else if (FAKELIGHT_ENABLED)
12928 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12929 else if (rsurface.uselightmaptexture)
12930 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12932 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12933 // then apply the texture to it
12934 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12935 R_Mesh_TexBind(0, layer->texture);
12936 R_Mesh_TexMatrix(0, &layer->texmatrix);
12937 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12938 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12939 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);
12943 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12944 R_Mesh_TexBind(0, layer->texture);
12945 R_Mesh_TexMatrix(0, &layer->texmatrix);
12946 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12947 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12948 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12949 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);
12951 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);
12954 case TEXTURELAYERTYPE_TEXTURE:
12955 // singletexture unlit texture with transparency support
12956 R_Mesh_TexBind(0, layer->texture);
12957 R_Mesh_TexMatrix(0, &layer->texmatrix);
12958 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12959 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12960 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);
12962 case TEXTURELAYERTYPE_FOG:
12963 // singletexture fogging
12964 if (layer->texture)
12966 R_Mesh_TexBind(0, layer->texture);
12967 R_Mesh_TexMatrix(0, &layer->texmatrix);
12968 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12969 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12973 R_Mesh_TexBind(0, 0);
12974 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12976 // generate a color array for the fog pass
12977 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12978 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12982 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12985 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12987 GL_DepthFunc(GL_LEQUAL);
12988 GL_AlphaTest(false);
12992 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12996 r_vertexgeneric_t *batchvertex;
12999 GL_AlphaTest(false);
13000 // R_Mesh_ResetTextureState();
13001 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13003 if(rsurface.texture && rsurface.texture->currentskinframe)
13005 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
13006 c[3] *= rsurface.texture->currentalpha;
13016 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
13018 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
13019 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
13020 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
13023 // brighten it up (as texture value 127 means "unlit")
13024 c[0] *= 2 * r_refdef.view.colorscale;
13025 c[1] *= 2 * r_refdef.view.colorscale;
13026 c[2] *= 2 * r_refdef.view.colorscale;
13028 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
13029 c[3] *= r_wateralpha.value;
13031 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
13033 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13034 GL_DepthMask(false);
13036 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
13038 GL_BlendFunc(GL_ONE, GL_ONE);
13039 GL_DepthMask(false);
13041 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
13043 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
13044 GL_DepthMask(false);
13046 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
13048 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
13049 GL_DepthMask(false);
13053 GL_BlendFunc(GL_ONE, GL_ZERO);
13054 GL_DepthMask(writedepth);
13057 if (r_showsurfaces.integer == 3)
13059 rsurface.passcolor4f = NULL;
13061 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
13063 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13065 rsurface.passcolor4f = NULL;
13066 rsurface.passcolor4f_vertexbuffer = 0;
13067 rsurface.passcolor4f_bufferoffset = 0;
13069 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
13071 qboolean applycolor = true;
13074 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13076 r_refdef.lightmapintensity = 1;
13077 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
13078 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
13080 else if (FAKELIGHT_ENABLED)
13082 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13084 r_refdef.lightmapintensity = r_fakelight_intensity.value;
13085 RSurf_DrawBatch_GL11_ApplyFakeLight();
13086 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
13090 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13092 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
13093 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
13094 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
13097 if(!rsurface.passcolor4f)
13098 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
13100 RSurf_DrawBatch_GL11_ApplyAmbient();
13101 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
13102 if(r_refdef.fogenabled)
13103 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
13104 RSurf_DrawBatch_GL11_ClampColor();
13106 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
13107 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13110 else if (!r_refdef.view.showdebug)
13112 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13113 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
13114 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
13116 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13117 Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
13119 R_Mesh_PrepareVertices_Generic_Unlock();
13122 else if (r_showsurfaces.integer == 4)
13124 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13125 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
13126 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
13128 unsigned char c = vi << 3;
13129 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13130 Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
13132 R_Mesh_PrepareVertices_Generic_Unlock();
13135 else if (r_showsurfaces.integer == 2)
13138 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13139 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
13140 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
13142 unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
13143 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
13144 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
13145 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
13146 Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
13147 Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
13148 Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
13150 R_Mesh_PrepareVertices_Generic_Unlock();
13151 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
13155 int texturesurfaceindex;
13157 const msurface_t *surface;
13158 unsigned char surfacecolor4ub[4];
13159 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13160 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
13162 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
13164 surface = texturesurfacelist[texturesurfaceindex];
13165 k = (int)(((size_t)surface) / sizeof(msurface_t));
13166 Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
13167 for (j = 0;j < surface->num_vertices;j++)
13169 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13170 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
13174 R_Mesh_PrepareVertices_Generic_Unlock();
13179 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13182 RSurf_SetupDepthAndCulling();
13183 if (r_showsurfaces.integer)
13185 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13188 switch (vid.renderpath)
13190 case RENDERPATH_GL20:
13191 case RENDERPATH_CGGL:
13192 case RENDERPATH_D3D9:
13193 case RENDERPATH_D3D10:
13194 case RENDERPATH_D3D11:
13195 case RENDERPATH_SOFT:
13196 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13198 case RENDERPATH_GL13:
13199 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13201 case RENDERPATH_GL11:
13202 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13208 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13211 RSurf_SetupDepthAndCulling();
13212 if (r_showsurfaces.integer)
13214 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13217 switch (vid.renderpath)
13219 case RENDERPATH_GL20:
13220 case RENDERPATH_CGGL:
13221 case RENDERPATH_D3D9:
13222 case RENDERPATH_D3D10:
13223 case RENDERPATH_D3D11:
13224 case RENDERPATH_SOFT:
13225 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13227 case RENDERPATH_GL13:
13228 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13230 case RENDERPATH_GL11:
13231 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13237 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13240 int texturenumsurfaces, endsurface;
13241 texture_t *texture;
13242 const msurface_t *surface;
13243 #define MAXBATCH_TRANSPARENTSURFACES 256
13244 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
13246 // if the model is static it doesn't matter what value we give for
13247 // wantnormals and wanttangents, so this logic uses only rules applicable
13248 // to a model, knowing that they are meaningless otherwise
13249 if (ent == r_refdef.scene.worldentity)
13250 RSurf_ActiveWorldEntity();
13251 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13252 RSurf_ActiveModelEntity(ent, false, false, false);
13255 switch (vid.renderpath)
13257 case RENDERPATH_GL20:
13258 case RENDERPATH_CGGL:
13259 case RENDERPATH_D3D9:
13260 case RENDERPATH_D3D10:
13261 case RENDERPATH_D3D11:
13262 case RENDERPATH_SOFT:
13263 RSurf_ActiveModelEntity(ent, true, true, false);
13265 case RENDERPATH_GL13:
13266 case RENDERPATH_GL11:
13267 RSurf_ActiveModelEntity(ent, true, false, false);
13272 if (r_transparentdepthmasking.integer)
13274 qboolean setup = false;
13275 for (i = 0;i < numsurfaces;i = j)
13278 surface = rsurface.modelsurfaces + surfacelist[i];
13279 texture = surface->texture;
13280 rsurface.texture = R_GetCurrentTexture(texture);
13281 rsurface.lightmaptexture = NULL;
13282 rsurface.deluxemaptexture = NULL;
13283 rsurface.uselightmaptexture = false;
13284 // scan ahead until we find a different texture
13285 endsurface = min(i + 1024, numsurfaces);
13286 texturenumsurfaces = 0;
13287 texturesurfacelist[texturenumsurfaces++] = surface;
13288 for (;j < endsurface;j++)
13290 surface = rsurface.modelsurfaces + surfacelist[j];
13291 if (texture != surface->texture)
13293 texturesurfacelist[texturenumsurfaces++] = surface;
13295 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
13297 // render the range of surfaces as depth
13301 GL_ColorMask(0,0,0,0);
13303 GL_DepthTest(true);
13304 GL_BlendFunc(GL_ONE, GL_ZERO);
13305 GL_DepthMask(true);
13306 GL_AlphaTest(false);
13307 // R_Mesh_ResetTextureState();
13308 R_SetupShader_DepthOrShadow();
13310 RSurf_SetupDepthAndCulling();
13311 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
13312 if (rsurface.batchvertex3fbuffer)
13313 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
13315 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
13319 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
13322 for (i = 0;i < numsurfaces;i = j)
13325 surface = rsurface.modelsurfaces + surfacelist[i];
13326 texture = surface->texture;
13327 rsurface.texture = R_GetCurrentTexture(texture);
13328 // scan ahead until we find a different texture
13329 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
13330 texturenumsurfaces = 0;
13331 texturesurfacelist[texturenumsurfaces++] = surface;
13332 if(FAKELIGHT_ENABLED)
13334 rsurface.lightmaptexture = NULL;
13335 rsurface.deluxemaptexture = NULL;
13336 rsurface.uselightmaptexture = false;
13337 for (;j < endsurface;j++)
13339 surface = rsurface.modelsurfaces + surfacelist[j];
13340 if (texture != surface->texture)
13342 texturesurfacelist[texturenumsurfaces++] = surface;
13347 rsurface.lightmaptexture = surface->lightmaptexture;
13348 rsurface.deluxemaptexture = surface->deluxemaptexture;
13349 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
13350 for (;j < endsurface;j++)
13352 surface = rsurface.modelsurfaces + surfacelist[j];
13353 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
13355 texturesurfacelist[texturenumsurfaces++] = surface;
13358 // render the range of surfaces
13359 if (ent == r_refdef.scene.worldentity)
13360 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13362 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13364 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13365 GL_AlphaTest(false);
13368 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
13370 // transparent surfaces get pushed off into the transparent queue
13371 int surfacelistindex;
13372 const msurface_t *surface;
13373 vec3_t tempcenter, center;
13374 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
13376 surface = texturesurfacelist[surfacelistindex];
13377 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
13378 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
13379 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
13380 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
13381 if (queueentity->transparent_offset) // transparent offset
13383 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
13384 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
13385 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
13387 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
13391 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
13393 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
13395 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
13397 RSurf_SetupDepthAndCulling();
13398 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
13399 if (rsurface.batchvertex3fbuffer)
13400 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
13402 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
13406 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
13408 const entity_render_t *queueentity = r_refdef.scene.worldentity;
13411 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13414 if (!rsurface.texture->currentnumlayers)
13416 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13417 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13419 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13421 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13422 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13423 else if (!rsurface.texture->currentnumlayers)
13425 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13427 // in the deferred case, transparent surfaces were queued during prepass
13428 if (!r_shadow_usingdeferredprepass)
13429 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13433 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13434 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13439 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13442 texture_t *texture;
13443 R_FrameData_SetMark();
13444 // break the surface list down into batches by texture and use of lightmapping
13445 for (i = 0;i < numsurfaces;i = j)
13448 // texture is the base texture pointer, rsurface.texture is the
13449 // current frame/skin the texture is directing us to use (for example
13450 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13451 // use skin 1 instead)
13452 texture = surfacelist[i]->texture;
13453 rsurface.texture = R_GetCurrentTexture(texture);
13454 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13456 // if this texture is not the kind we want, skip ahead to the next one
13457 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13461 if(FAKELIGHT_ENABLED || depthonly || prepass)
13463 rsurface.lightmaptexture = NULL;
13464 rsurface.deluxemaptexture = NULL;
13465 rsurface.uselightmaptexture = false;
13466 // simply scan ahead until we find a different texture or lightmap state
13467 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13472 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13473 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13474 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13475 // simply scan ahead until we find a different texture or lightmap state
13476 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13479 // render the range of surfaces
13480 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
13482 R_FrameData_ReturnToMark();
13485 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
13489 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13492 if (!rsurface.texture->currentnumlayers)
13494 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13495 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13497 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13499 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13500 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13501 else if (!rsurface.texture->currentnumlayers)
13503 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13505 // in the deferred case, transparent surfaces were queued during prepass
13506 if (!r_shadow_usingdeferredprepass)
13507 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13511 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13512 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13517 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13520 texture_t *texture;
13521 R_FrameData_SetMark();
13522 // break the surface list down into batches by texture and use of lightmapping
13523 for (i = 0;i < numsurfaces;i = j)
13526 // texture is the base texture pointer, rsurface.texture is the
13527 // current frame/skin the texture is directing us to use (for example
13528 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13529 // use skin 1 instead)
13530 texture = surfacelist[i]->texture;
13531 rsurface.texture = R_GetCurrentTexture(texture);
13532 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13534 // if this texture is not the kind we want, skip ahead to the next one
13535 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13539 if(FAKELIGHT_ENABLED || depthonly || prepass)
13541 rsurface.lightmaptexture = NULL;
13542 rsurface.deluxemaptexture = NULL;
13543 rsurface.uselightmaptexture = false;
13544 // simply scan ahead until we find a different texture or lightmap state
13545 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13550 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13551 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13552 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13553 // simply scan ahead until we find a different texture or lightmap state
13554 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13557 // render the range of surfaces
13558 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
13560 R_FrameData_ReturnToMark();
13563 float locboxvertex3f[6*4*3] =
13565 1,0,1, 1,0,0, 1,1,0, 1,1,1,
13566 0,1,1, 0,1,0, 0,0,0, 0,0,1,
13567 1,1,1, 1,1,0, 0,1,0, 0,1,1,
13568 0,0,1, 0,0,0, 1,0,0, 1,0,1,
13569 0,0,1, 1,0,1, 1,1,1, 0,1,1,
13570 1,0,0, 0,0,0, 0,1,0, 1,1,0
13573 unsigned short locboxelements[6*2*3] =
13578 12,13,14, 12,14,15,
13579 16,17,18, 16,18,19,
13583 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13586 cl_locnode_t *loc = (cl_locnode_t *)ent;
13588 float vertex3f[6*4*3];
13590 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13591 GL_DepthMask(false);
13592 GL_DepthRange(0, 1);
13593 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13594 GL_DepthTest(true);
13595 GL_CullFace(GL_NONE);
13596 R_EntityMatrix(&identitymatrix);
13598 // R_Mesh_ResetTextureState();
13600 i = surfacelist[0];
13601 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13602 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13603 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13604 surfacelist[0] < 0 ? 0.5f : 0.125f);
13606 if (VectorCompare(loc->mins, loc->maxs))
13608 VectorSet(size, 2, 2, 2);
13609 VectorMA(loc->mins, -0.5f, size, mins);
13613 VectorCopy(loc->mins, mins);
13614 VectorSubtract(loc->maxs, loc->mins, size);
13617 for (i = 0;i < 6*4*3;)
13618 for (j = 0;j < 3;j++, i++)
13619 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13621 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13622 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13623 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13626 void R_DrawLocs(void)
13629 cl_locnode_t *loc, *nearestloc;
13631 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13632 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13634 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13635 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13639 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13641 if (decalsystem->decals)
13642 Mem_Free(decalsystem->decals);
13643 memset(decalsystem, 0, sizeof(*decalsystem));
13646 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)
13649 tridecal_t *decals;
13652 // expand or initialize the system
13653 if (decalsystem->maxdecals <= decalsystem->numdecals)
13655 decalsystem_t old = *decalsystem;
13656 qboolean useshortelements;
13657 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13658 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13659 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)));
13660 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13661 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13662 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13663 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13664 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13665 if (decalsystem->numdecals)
13666 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13668 Mem_Free(old.decals);
13669 for (i = 0;i < decalsystem->maxdecals*3;i++)
13670 decalsystem->element3i[i] = i;
13671 if (useshortelements)
13672 for (i = 0;i < decalsystem->maxdecals*3;i++)
13673 decalsystem->element3s[i] = i;
13676 // grab a decal and search for another free slot for the next one
13677 decals = decalsystem->decals;
13678 decal = decalsystem->decals + (i = decalsystem->freedecal++);
13679 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13681 decalsystem->freedecal = i;
13682 if (decalsystem->numdecals <= i)
13683 decalsystem->numdecals = i + 1;
13685 // initialize the decal
13687 decal->triangleindex = triangleindex;
13688 decal->surfaceindex = surfaceindex;
13689 decal->decalsequence = decalsequence;
13690 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13691 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13692 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13693 decal->color4ub[0][3] = 255;
13694 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13695 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13696 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13697 decal->color4ub[1][3] = 255;
13698 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13699 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13700 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13701 decal->color4ub[2][3] = 255;
13702 decal->vertex3f[0][0] = v0[0];
13703 decal->vertex3f[0][1] = v0[1];
13704 decal->vertex3f[0][2] = v0[2];
13705 decal->vertex3f[1][0] = v1[0];
13706 decal->vertex3f[1][1] = v1[1];
13707 decal->vertex3f[1][2] = v1[2];
13708 decal->vertex3f[2][0] = v2[0];
13709 decal->vertex3f[2][1] = v2[1];
13710 decal->vertex3f[2][2] = v2[2];
13711 decal->texcoord2f[0][0] = t0[0];
13712 decal->texcoord2f[0][1] = t0[1];
13713 decal->texcoord2f[1][0] = t1[0];
13714 decal->texcoord2f[1][1] = t1[1];
13715 decal->texcoord2f[2][0] = t2[0];
13716 decal->texcoord2f[2][1] = t2[1];
13719 extern cvar_t cl_decals_bias;
13720 extern cvar_t cl_decals_models;
13721 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13722 // baseparms, parms, temps
13723 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)
13728 const float *vertex3f;
13730 float points[2][9][3];
13737 e = rsurface.modelelement3i + 3*triangleindex;
13739 vertex3f = rsurface.modelvertex3f;
13741 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13743 index = 3*e[cornerindex];
13744 VectorCopy(vertex3f + index, v[cornerindex]);
13747 //TriangleNormal(v[0], v[1], v[2], normal);
13748 //if (DotProduct(normal, localnormal) < 0.0f)
13750 // clip by each of the box planes formed from the projection matrix
13751 // if anything survives, we emit the decal
13752 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]);
13755 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]);
13758 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]);
13761 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]);
13764 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]);
13767 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]);
13770 // some part of the triangle survived, so we have to accept it...
13773 // dynamic always uses the original triangle
13775 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13777 index = 3*e[cornerindex];
13778 VectorCopy(vertex3f + index, v[cornerindex]);
13781 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13783 // convert vertex positions to texcoords
13784 Matrix4x4_Transform(projection, v[cornerindex], temp);
13785 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13786 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13787 // calculate distance fade from the projection origin
13788 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13789 f = bound(0.0f, f, 1.0f);
13790 c[cornerindex][0] = r * f;
13791 c[cornerindex][1] = g * f;
13792 c[cornerindex][2] = b * f;
13793 c[cornerindex][3] = 1.0f;
13794 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13797 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);
13799 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13800 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);
13802 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)
13804 matrix4x4_t projection;
13805 decalsystem_t *decalsystem;
13808 const msurface_t *surface;
13809 const msurface_t *surfaces;
13810 const int *surfacelist;
13811 const texture_t *texture;
13813 int numsurfacelist;
13814 int surfacelistindex;
13817 float localorigin[3];
13818 float localnormal[3];
13819 float localmins[3];
13820 float localmaxs[3];
13823 float planes[6][4];
13826 int bih_triangles_count;
13827 int bih_triangles[256];
13828 int bih_surfaces[256];
13830 decalsystem = &ent->decalsystem;
13831 model = ent->model;
13832 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13834 R_DecalSystem_Reset(&ent->decalsystem);
13838 if (!model->brush.data_leafs && !cl_decals_models.integer)
13840 if (decalsystem->model)
13841 R_DecalSystem_Reset(decalsystem);
13845 if (decalsystem->model != model)
13846 R_DecalSystem_Reset(decalsystem);
13847 decalsystem->model = model;
13849 RSurf_ActiveModelEntity(ent, false, false, false);
13851 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13852 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13853 VectorNormalize(localnormal);
13854 localsize = worldsize*rsurface.inversematrixscale;
13855 localmins[0] = localorigin[0] - localsize;
13856 localmins[1] = localorigin[1] - localsize;
13857 localmins[2] = localorigin[2] - localsize;
13858 localmaxs[0] = localorigin[0] + localsize;
13859 localmaxs[1] = localorigin[1] + localsize;
13860 localmaxs[2] = localorigin[2] + localsize;
13862 //VectorCopy(localnormal, planes[4]);
13863 //VectorVectors(planes[4], planes[2], planes[0]);
13864 AnglesFromVectors(angles, localnormal, NULL, false);
13865 AngleVectors(angles, planes[0], planes[2], planes[4]);
13866 VectorNegate(planes[0], planes[1]);
13867 VectorNegate(planes[2], planes[3]);
13868 VectorNegate(planes[4], planes[5]);
13869 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13870 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13871 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13872 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13873 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13874 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13879 matrix4x4_t forwardprojection;
13880 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13881 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13886 float projectionvector[4][3];
13887 VectorScale(planes[0], ilocalsize, projectionvector[0]);
13888 VectorScale(planes[2], ilocalsize, projectionvector[1]);
13889 VectorScale(planes[4], ilocalsize, projectionvector[2]);
13890 projectionvector[0][0] = planes[0][0] * ilocalsize;
13891 projectionvector[0][1] = planes[1][0] * ilocalsize;
13892 projectionvector[0][2] = planes[2][0] * ilocalsize;
13893 projectionvector[1][0] = planes[0][1] * ilocalsize;
13894 projectionvector[1][1] = planes[1][1] * ilocalsize;
13895 projectionvector[1][2] = planes[2][1] * ilocalsize;
13896 projectionvector[2][0] = planes[0][2] * ilocalsize;
13897 projectionvector[2][1] = planes[1][2] * ilocalsize;
13898 projectionvector[2][2] = planes[2][2] * ilocalsize;
13899 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13900 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13901 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13902 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13906 dynamic = model->surfmesh.isanimated;
13907 numsurfacelist = model->nummodelsurfaces;
13908 surfacelist = model->sortedmodelsurfaces;
13909 surfaces = model->data_surfaces;
13912 bih_triangles_count = -1;
13915 if(model->render_bih.numleafs)
13916 bih = &model->render_bih;
13917 else if(model->collision_bih.numleafs)
13918 bih = &model->collision_bih;
13921 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13922 if(bih_triangles_count == 0)
13924 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13926 if(bih_triangles_count > 0)
13928 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13930 surfaceindex = bih_surfaces[triangleindex];
13931 surface = surfaces + surfaceindex;
13932 texture = surface->texture;
13933 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13935 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13937 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13942 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13944 surfaceindex = surfacelist[surfacelistindex];
13945 surface = surfaces + surfaceindex;
13946 // check cull box first because it rejects more than any other check
13947 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13949 // skip transparent surfaces
13950 texture = surface->texture;
13951 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13953 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13955 numtriangles = surface->num_triangles;
13956 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13957 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13962 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13963 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)
13965 int renderentityindex;
13966 float worldmins[3];
13967 float worldmaxs[3];
13968 entity_render_t *ent;
13970 if (!cl_decals_newsystem.integer)
13973 worldmins[0] = worldorigin[0] - worldsize;
13974 worldmins[1] = worldorigin[1] - worldsize;
13975 worldmins[2] = worldorigin[2] - worldsize;
13976 worldmaxs[0] = worldorigin[0] + worldsize;
13977 worldmaxs[1] = worldorigin[1] + worldsize;
13978 worldmaxs[2] = worldorigin[2] + worldsize;
13980 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13982 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13984 ent = r_refdef.scene.entities[renderentityindex];
13985 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13988 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13992 typedef struct r_decalsystem_splatqueue_s
13994 vec3_t worldorigin;
13995 vec3_t worldnormal;
14001 r_decalsystem_splatqueue_t;
14003 int r_decalsystem_numqueued = 0;
14004 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
14006 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)
14008 r_decalsystem_splatqueue_t *queue;
14010 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
14013 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
14014 VectorCopy(worldorigin, queue->worldorigin);
14015 VectorCopy(worldnormal, queue->worldnormal);
14016 Vector4Set(queue->color, r, g, b, a);
14017 Vector4Set(queue->tcrange, s1, t1, s2, t2);
14018 queue->worldsize = worldsize;
14019 queue->decalsequence = cl.decalsequence++;
14022 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
14025 r_decalsystem_splatqueue_t *queue;
14027 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
14028 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);
14029 r_decalsystem_numqueued = 0;
14032 extern cvar_t cl_decals_max;
14033 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
14036 decalsystem_t *decalsystem = &ent->decalsystem;
14043 if (!decalsystem->numdecals)
14046 if (r_showsurfaces.integer)
14049 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
14051 R_DecalSystem_Reset(decalsystem);
14055 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
14056 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
14058 if (decalsystem->lastupdatetime)
14059 frametime = (cl.time - decalsystem->lastupdatetime);
14062 decalsystem->lastupdatetime = cl.time;
14063 decal = decalsystem->decals;
14064 numdecals = decalsystem->numdecals;
14066 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
14068 if (decal->color4ub[0][3])
14070 decal->lived += frametime;
14071 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
14073 memset(decal, 0, sizeof(*decal));
14074 if (decalsystem->freedecal > i)
14075 decalsystem->freedecal = i;
14079 decal = decalsystem->decals;
14080 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
14083 // collapse the array by shuffling the tail decals into the gaps
14086 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
14087 decalsystem->freedecal++;
14088 if (decalsystem->freedecal == numdecals)
14090 decal[decalsystem->freedecal] = decal[--numdecals];
14093 decalsystem->numdecals = numdecals;
14095 if (numdecals <= 0)
14097 // if there are no decals left, reset decalsystem
14098 R_DecalSystem_Reset(decalsystem);
14102 extern skinframe_t *decalskinframe;
14103 static void R_DrawModelDecals_Entity(entity_render_t *ent)
14106 decalsystem_t *decalsystem = &ent->decalsystem;
14115 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
14118 numdecals = decalsystem->numdecals;
14122 if (r_showsurfaces.integer)
14125 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
14127 R_DecalSystem_Reset(decalsystem);
14131 // if the model is static it doesn't matter what value we give for
14132 // wantnormals and wanttangents, so this logic uses only rules applicable
14133 // to a model, knowing that they are meaningless otherwise
14134 if (ent == r_refdef.scene.worldentity)
14135 RSurf_ActiveWorldEntity();
14137 RSurf_ActiveModelEntity(ent, false, false, false);
14139 decalsystem->lastupdatetime = cl.time;
14140 decal = decalsystem->decals;
14142 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
14144 // update vertex positions for animated models
14145 v3f = decalsystem->vertex3f;
14146 c4f = decalsystem->color4f;
14147 t2f = decalsystem->texcoord2f;
14148 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
14150 if (!decal->color4ub[0][3])
14153 if (surfacevisible && !surfacevisible[decal->surfaceindex])
14156 // update color values for fading decals
14157 if (decal->lived >= cl_decals_time.value)
14159 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
14160 alpha *= (1.0f/255.0f);
14163 alpha = 1.0f/255.0f;
14165 c4f[ 0] = decal->color4ub[0][0] * alpha;
14166 c4f[ 1] = decal->color4ub[0][1] * alpha;
14167 c4f[ 2] = decal->color4ub[0][2] * alpha;
14169 c4f[ 4] = decal->color4ub[1][0] * alpha;
14170 c4f[ 5] = decal->color4ub[1][1] * alpha;
14171 c4f[ 6] = decal->color4ub[1][2] * alpha;
14173 c4f[ 8] = decal->color4ub[2][0] * alpha;
14174 c4f[ 9] = decal->color4ub[2][1] * alpha;
14175 c4f[10] = decal->color4ub[2][2] * alpha;
14178 t2f[0] = decal->texcoord2f[0][0];
14179 t2f[1] = decal->texcoord2f[0][1];
14180 t2f[2] = decal->texcoord2f[1][0];
14181 t2f[3] = decal->texcoord2f[1][1];
14182 t2f[4] = decal->texcoord2f[2][0];
14183 t2f[5] = decal->texcoord2f[2][1];
14185 // update vertex positions for animated models
14186 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
14188 e = rsurface.modelelement3i + 3*decal->triangleindex;
14189 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
14190 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
14191 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
14195 VectorCopy(decal->vertex3f[0], v3f);
14196 VectorCopy(decal->vertex3f[1], v3f + 3);
14197 VectorCopy(decal->vertex3f[2], v3f + 6);
14200 if (r_refdef.fogenabled)
14202 alpha = RSurf_FogVertex(v3f);
14203 VectorScale(c4f, alpha, c4f);
14204 alpha = RSurf_FogVertex(v3f + 3);
14205 VectorScale(c4f + 4, alpha, c4f + 4);
14206 alpha = RSurf_FogVertex(v3f + 6);
14207 VectorScale(c4f + 8, alpha, c4f + 8);
14218 r_refdef.stats.drawndecals += numtris;
14220 // now render the decals all at once
14221 // (this assumes they all use one particle font texture!)
14222 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);
14223 // R_Mesh_ResetTextureState();
14224 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
14225 GL_DepthMask(false);
14226 GL_DepthRange(0, 1);
14227 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
14228 GL_DepthTest(true);
14229 GL_CullFace(GL_NONE);
14230 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
14231 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
14232 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
14236 static void R_DrawModelDecals(void)
14240 // fade faster when there are too many decals
14241 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14242 for (i = 0;i < r_refdef.scene.numentities;i++)
14243 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14245 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
14246 for (i = 0;i < r_refdef.scene.numentities;i++)
14247 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14248 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
14250 R_DecalSystem_ApplySplatEntitiesQueue();
14252 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14253 for (i = 0;i < r_refdef.scene.numentities;i++)
14254 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14256 r_refdef.stats.totaldecals += numdecals;
14258 if (r_showsurfaces.integer)
14261 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
14263 for (i = 0;i < r_refdef.scene.numentities;i++)
14265 if (!r_refdef.viewcache.entityvisible[i])
14267 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14268 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
14272 extern cvar_t mod_collision_bih;
14273 void R_DrawDebugModel(void)
14275 entity_render_t *ent = rsurface.entity;
14276 int i, j, k, l, flagsmask;
14277 const msurface_t *surface;
14278 dp_model_t *model = ent->model;
14281 switch(vid.renderpath)
14283 case RENDERPATH_GL11:
14284 case RENDERPATH_GL13:
14285 case RENDERPATH_GL20:
14286 case RENDERPATH_CGGL:
14288 case RENDERPATH_D3D9:
14289 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14291 case RENDERPATH_D3D10:
14292 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14294 case RENDERPATH_D3D11:
14295 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14297 case RENDERPATH_SOFT:
14298 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14302 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
14304 // R_Mesh_ResetTextureState();
14305 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
14306 GL_DepthRange(0, 1);
14307 GL_DepthTest(!r_showdisabledepthtest.integer);
14308 GL_DepthMask(false);
14309 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14311 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
14315 qboolean cullbox = ent == r_refdef.scene.worldentity;
14316 const q3mbrush_t *brush;
14317 const bih_t *bih = &model->collision_bih;
14318 const bih_leaf_t *bihleaf;
14319 float vertex3f[3][3];
14320 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
14322 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
14324 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
14326 switch (bihleaf->type)
14329 brush = model->brush.data_brushes + bihleaf->itemindex;
14330 if (brush->colbrushf && brush->colbrushf->numtriangles)
14332 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);
14333 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
14334 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
14337 case BIH_COLLISIONTRIANGLE:
14338 triangleindex = bihleaf->itemindex;
14339 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
14340 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
14341 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
14342 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);
14343 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14344 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14346 case BIH_RENDERTRIANGLE:
14347 triangleindex = bihleaf->itemindex;
14348 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
14349 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
14350 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
14351 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);
14352 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14353 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14359 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
14361 if (r_showtris.integer || (r_shownormals.value != 0))
14363 if (r_showdisabledepthtest.integer)
14365 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14366 GL_DepthMask(false);
14370 GL_BlendFunc(GL_ONE, GL_ZERO);
14371 GL_DepthMask(true);
14373 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
14375 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
14377 rsurface.texture = R_GetCurrentTexture(surface->texture);
14378 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
14380 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
14381 if (r_showtris.value > 0)
14383 if (!rsurface.texture->currentlayers->depthmask)
14384 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
14385 else if (ent == r_refdef.scene.worldentity)
14386 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
14388 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
14389 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
14390 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
14392 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
14395 if (r_shownormals.value < 0)
14397 qglBegin(GL_LINES);
14398 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14400 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14401 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14402 qglVertex3f(v[0], v[1], v[2]);
14403 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14404 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14405 qglVertex3f(v[0], v[1], v[2]);
14410 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
14412 qglBegin(GL_LINES);
14413 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14415 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14416 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14417 qglVertex3f(v[0], v[1], v[2]);
14418 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14419 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14420 qglVertex3f(v[0], v[1], v[2]);
14424 qglBegin(GL_LINES);
14425 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14427 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14428 GL_Color(0, r_refdef.view.colorscale, 0, 1);
14429 qglVertex3f(v[0], v[1], v[2]);
14430 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
14431 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14432 qglVertex3f(v[0], v[1], v[2]);
14436 qglBegin(GL_LINES);
14437 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14439 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14440 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14441 qglVertex3f(v[0], v[1], v[2]);
14442 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14443 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14444 qglVertex3f(v[0], v[1], v[2]);
14451 rsurface.texture = NULL;
14455 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
14456 int r_maxsurfacelist = 0;
14457 const msurface_t **r_surfacelist = NULL;
14458 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14460 int i, j, endj, flagsmask;
14461 dp_model_t *model = r_refdef.scene.worldmodel;
14462 msurface_t *surfaces;
14463 unsigned char *update;
14464 int numsurfacelist = 0;
14468 if (r_maxsurfacelist < model->num_surfaces)
14470 r_maxsurfacelist = model->num_surfaces;
14472 Mem_Free((msurface_t**)r_surfacelist);
14473 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14476 RSurf_ActiveWorldEntity();
14478 surfaces = model->data_surfaces;
14479 update = model->brushq1.lightmapupdateflags;
14481 // update light styles on this submodel
14482 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14484 model_brush_lightstyleinfo_t *style;
14485 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14487 if (style->value != r_refdef.scene.lightstylevalue[style->style])
14489 int *list = style->surfacelist;
14490 style->value = r_refdef.scene.lightstylevalue[style->style];
14491 for (j = 0;j < style->numsurfaces;j++)
14492 update[list[j]] = true;
14497 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14501 R_DrawDebugModel();
14502 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14506 rsurface.lightmaptexture = NULL;
14507 rsurface.deluxemaptexture = NULL;
14508 rsurface.uselightmaptexture = false;
14509 rsurface.texture = NULL;
14510 rsurface.rtlight = NULL;
14511 numsurfacelist = 0;
14512 // add visible surfaces to draw list
14513 for (i = 0;i < model->nummodelsurfaces;i++)
14515 j = model->sortedmodelsurfaces[i];
14516 if (r_refdef.viewcache.world_surfacevisible[j])
14517 r_surfacelist[numsurfacelist++] = surfaces + j;
14519 // update lightmaps if needed
14520 if (model->brushq1.firstrender)
14522 model->brushq1.firstrender = false;
14523 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14525 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14529 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14530 if (r_refdef.viewcache.world_surfacevisible[j])
14532 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14534 // don't do anything if there were no surfaces
14535 if (!numsurfacelist)
14537 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14540 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14541 GL_AlphaTest(false);
14543 // add to stats if desired
14544 if (r_speeds.integer && !skysurfaces && !depthonly)
14546 r_refdef.stats.world_surfaces += numsurfacelist;
14547 for (j = 0;j < numsurfacelist;j++)
14548 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
14551 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14554 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14556 int i, j, endj, flagsmask;
14557 dp_model_t *model = ent->model;
14558 msurface_t *surfaces;
14559 unsigned char *update;
14560 int numsurfacelist = 0;
14564 if (r_maxsurfacelist < model->num_surfaces)
14566 r_maxsurfacelist = model->num_surfaces;
14568 Mem_Free((msurface_t **)r_surfacelist);
14569 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14572 // if the model is static it doesn't matter what value we give for
14573 // wantnormals and wanttangents, so this logic uses only rules applicable
14574 // to a model, knowing that they are meaningless otherwise
14575 if (ent == r_refdef.scene.worldentity)
14576 RSurf_ActiveWorldEntity();
14577 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14578 RSurf_ActiveModelEntity(ent, false, false, false);
14580 RSurf_ActiveModelEntity(ent, true, true, true);
14581 else if (depthonly)
14583 switch (vid.renderpath)
14585 case RENDERPATH_GL20:
14586 case RENDERPATH_CGGL:
14587 case RENDERPATH_D3D9:
14588 case RENDERPATH_D3D10:
14589 case RENDERPATH_D3D11:
14590 case RENDERPATH_SOFT:
14591 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14593 case RENDERPATH_GL13:
14594 case RENDERPATH_GL11:
14595 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14601 switch (vid.renderpath)
14603 case RENDERPATH_GL20:
14604 case RENDERPATH_CGGL:
14605 case RENDERPATH_D3D9:
14606 case RENDERPATH_D3D10:
14607 case RENDERPATH_D3D11:
14608 case RENDERPATH_SOFT:
14609 RSurf_ActiveModelEntity(ent, true, true, false);
14611 case RENDERPATH_GL13:
14612 case RENDERPATH_GL11:
14613 RSurf_ActiveModelEntity(ent, true, false, false);
14618 surfaces = model->data_surfaces;
14619 update = model->brushq1.lightmapupdateflags;
14621 // update light styles
14622 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14624 model_brush_lightstyleinfo_t *style;
14625 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14627 if (style->value != r_refdef.scene.lightstylevalue[style->style])
14629 int *list = style->surfacelist;
14630 style->value = r_refdef.scene.lightstylevalue[style->style];
14631 for (j = 0;j < style->numsurfaces;j++)
14632 update[list[j]] = true;
14637 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14641 R_DrawDebugModel();
14642 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14646 rsurface.lightmaptexture = NULL;
14647 rsurface.deluxemaptexture = NULL;
14648 rsurface.uselightmaptexture = false;
14649 rsurface.texture = NULL;
14650 rsurface.rtlight = NULL;
14651 numsurfacelist = 0;
14652 // add visible surfaces to draw list
14653 for (i = 0;i < model->nummodelsurfaces;i++)
14654 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14655 // don't do anything if there were no surfaces
14656 if (!numsurfacelist)
14658 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14661 // update lightmaps if needed
14665 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14670 R_BuildLightMap(ent, surfaces + j);
14675 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14677 R_BuildLightMap(ent, surfaces + j);
14678 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14679 GL_AlphaTest(false);
14681 // add to stats if desired
14682 if (r_speeds.integer && !skysurfaces && !depthonly)
14684 r_refdef.stats.entities_surfaces += numsurfacelist;
14685 for (j = 0;j < numsurfacelist;j++)
14686 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14689 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14692 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14694 static texture_t texture;
14695 static msurface_t surface;
14696 const msurface_t *surfacelist = &surface;
14698 // fake enough texture and surface state to render this geometry
14700 texture.update_lastrenderframe = -1; // regenerate this texture
14701 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14702 texture.currentskinframe = skinframe;
14703 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14704 texture.offsetmapping = OFFSETMAPPING_OFF;
14705 texture.offsetscale = 1;
14706 texture.specularscalemod = 1;
14707 texture.specularpowermod = 1;
14709 surface.texture = &texture;
14710 surface.num_triangles = numtriangles;
14711 surface.num_firsttriangle = firsttriangle;
14712 surface.num_vertices = numvertices;
14713 surface.num_firstvertex = firstvertex;
14716 rsurface.texture = R_GetCurrentTexture(surface.texture);
14717 rsurface.lightmaptexture = NULL;
14718 rsurface.deluxemaptexture = NULL;
14719 rsurface.uselightmaptexture = false;
14720 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14723 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)
14725 static msurface_t surface;
14726 const msurface_t *surfacelist = &surface;
14728 // fake enough texture and surface state to render this geometry
14729 surface.texture = texture;
14730 surface.num_triangles = numtriangles;
14731 surface.num_firsttriangle = firsttriangle;
14732 surface.num_vertices = numvertices;
14733 surface.num_firstvertex = firstvertex;
14736 rsurface.texture = R_GetCurrentTexture(surface.texture);
14737 rsurface.lightmaptexture = NULL;
14738 rsurface.deluxemaptexture = NULL;
14739 rsurface.uselightmaptexture = false;
14740 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);