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)"};
181 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
182 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
183 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
184 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
185 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
186 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
188 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"};
190 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"};
192 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
194 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
195 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"};
196 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
197 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
198 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
199 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
200 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)"};
201 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
202 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
204 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
205 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"};
207 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)"};
209 extern cvar_t v_glslgamma;
211 extern qboolean v_flipped_state;
213 static struct r_bloomstate_s
218 int bloomwidth, bloomheight;
220 int screentexturewidth, screentextureheight;
221 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
223 int bloomtexturewidth, bloomtextureheight;
224 rtexture_t *texture_bloom;
226 // arrays for rendering the screen passes
227 float screentexcoord2f[8];
228 float bloomtexcoord2f[8];
229 float offsettexcoord2f[8];
231 r_viewport_t viewport;
235 r_waterstate_t r_waterstate;
237 /// shadow volume bsp struct with automatically growing nodes buffer
240 rtexture_t *r_texture_blanknormalmap;
241 rtexture_t *r_texture_white;
242 rtexture_t *r_texture_grey128;
243 rtexture_t *r_texture_black;
244 rtexture_t *r_texture_notexture;
245 rtexture_t *r_texture_whitecube;
246 rtexture_t *r_texture_normalizationcube;
247 rtexture_t *r_texture_fogattenuation;
248 rtexture_t *r_texture_fogheighttexture;
249 rtexture_t *r_texture_gammaramps;
250 unsigned int r_texture_gammaramps_serial;
251 //rtexture_t *r_texture_fogintensity;
252 rtexture_t *r_texture_reflectcube;
254 // TODO: hash lookups?
255 typedef struct cubemapinfo_s
262 int r_texture_numcubemaps;
263 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
265 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
266 unsigned int r_numqueries;
267 unsigned int r_maxqueries;
269 typedef struct r_qwskincache_s
271 char name[MAX_QPATH];
272 skinframe_t *skinframe;
276 static r_qwskincache_t *r_qwskincache;
277 static int r_qwskincache_size;
279 /// vertex coordinates for a quad that covers the screen exactly
280 extern const float r_screenvertex3f[12];
281 extern const float r_d3dscreenvertex3f[12];
282 const float r_screenvertex3f[12] =
289 const float r_d3dscreenvertex3f[12] =
297 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
300 for (i = 0;i < verts;i++)
311 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
314 for (i = 0;i < verts;i++)
324 // FIXME: move this to client?
327 if (gamemode == GAME_NEHAHRA)
329 Cvar_Set("gl_fogenable", "0");
330 Cvar_Set("gl_fogdensity", "0.2");
331 Cvar_Set("gl_fogred", "0.3");
332 Cvar_Set("gl_foggreen", "0.3");
333 Cvar_Set("gl_fogblue", "0.3");
335 r_refdef.fog_density = 0;
336 r_refdef.fog_red = 0;
337 r_refdef.fog_green = 0;
338 r_refdef.fog_blue = 0;
339 r_refdef.fog_alpha = 1;
340 r_refdef.fog_start = 0;
341 r_refdef.fog_end = 16384;
342 r_refdef.fog_height = 1<<30;
343 r_refdef.fog_fadedepth = 128;
344 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
347 static void R_BuildBlankTextures(void)
349 unsigned char data[4];
350 data[2] = 128; // normal X
351 data[1] = 128; // normal Y
352 data[0] = 255; // normal Z
353 data[3] = 128; // height
354 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
359 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
364 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
369 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
372 static void R_BuildNoTexture(void)
375 unsigned char pix[16][16][4];
376 // this makes a light grey/dark grey checkerboard texture
377 for (y = 0;y < 16;y++)
379 for (x = 0;x < 16;x++)
381 if ((y < 8) ^ (x < 8))
397 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
400 static void R_BuildWhiteCube(void)
402 unsigned char data[6*1*1*4];
403 memset(data, 255, sizeof(data));
404 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
407 static void R_BuildNormalizationCube(void)
411 vec_t s, t, intensity;
414 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
415 for (side = 0;side < 6;side++)
417 for (y = 0;y < NORMSIZE;y++)
419 for (x = 0;x < NORMSIZE;x++)
421 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
422 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
457 intensity = 127.0f / sqrt(DotProduct(v, v));
458 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
459 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
460 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
461 data[((side*64+y)*64+x)*4+3] = 255;
465 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
469 static void R_BuildFogTexture(void)
473 unsigned char data1[FOGWIDTH][4];
474 //unsigned char data2[FOGWIDTH][4];
477 r_refdef.fogmasktable_start = r_refdef.fog_start;
478 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
479 r_refdef.fogmasktable_range = r_refdef.fogrange;
480 r_refdef.fogmasktable_density = r_refdef.fog_density;
482 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
483 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
485 d = (x * r - r_refdef.fogmasktable_start);
486 if(developer_extra.integer)
487 Con_DPrintf("%f ", d);
489 if (r_fog_exp2.integer)
490 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
492 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
493 if(developer_extra.integer)
494 Con_DPrintf(" : %f ", alpha);
495 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
496 if(developer_extra.integer)
497 Con_DPrintf(" = %f\n", alpha);
498 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
501 for (x = 0;x < FOGWIDTH;x++)
503 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
508 //data2[x][0] = 255 - b;
509 //data2[x][1] = 255 - b;
510 //data2[x][2] = 255 - b;
513 if (r_texture_fogattenuation)
515 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
516 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
520 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
521 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
525 static void R_BuildFogHeightTexture(void)
527 unsigned char *inpixels;
535 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
536 if (r_refdef.fogheighttexturename[0])
537 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
540 r_refdef.fog_height_tablesize = 0;
541 if (r_texture_fogheighttexture)
542 R_FreeTexture(r_texture_fogheighttexture);
543 r_texture_fogheighttexture = NULL;
544 if (r_refdef.fog_height_table2d)
545 Mem_Free(r_refdef.fog_height_table2d);
546 r_refdef.fog_height_table2d = NULL;
547 if (r_refdef.fog_height_table1d)
548 Mem_Free(r_refdef.fog_height_table1d);
549 r_refdef.fog_height_table1d = NULL;
553 r_refdef.fog_height_tablesize = size;
554 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
555 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
556 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
558 // LordHavoc: now the magic - what is that table2d for? it is a cooked
559 // average fog color table accounting for every fog layer between a point
560 // and the camera. (Note: attenuation is handled separately!)
561 for (y = 0;y < size;y++)
563 for (x = 0;x < size;x++)
569 for (j = x;j <= y;j++)
571 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
577 for (j = x;j >= y;j--)
579 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
584 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
585 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
586 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
587 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
590 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
593 //=======================================================================================================================================================
595 static const char *builtinshaderstring =
596 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
597 "// written by Forest 'LordHavoc' Hale\n"
598 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
600 "// GL ES shaders use precision modifiers, standard GL does not\n"
607 "#ifdef VERTEX_SHADER\n"
608 "attribute vec4 Attrib_Position; // vertex\n"
609 "attribute vec4 Attrib_Color; // color\n"
610 "attribute vec4 Attrib_TexCoord0; // material texcoords\n"
611 "attribute vec3 Attrib_TexCoord1; // svector\n"
612 "attribute vec3 Attrib_TexCoord2; // tvector\n"
613 "attribute vec3 Attrib_TexCoord3; // normal\n"
614 "attribute vec4 Attrib_TexCoord4; // lightmap texcoords\n"
616 "varying lowp vec4 VertexColor;\n"
618 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
621 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
622 "#define USELIGHTMAP\n"
624 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
625 "#define USEEYEVECTOR\n"
628 "#ifdef USESHADOWMAP2D\n"
629 "# ifdef GL_EXT_gpu_shader4\n"
630 "# extension GL_EXT_gpu_shader4 : enable\n"
632 "# ifdef GL_ARB_texture_gather\n"
633 "# extension GL_ARB_texture_gather : enable\n"
635 "# ifdef GL_AMD_texture_texture4\n"
636 "# extension GL_AMD_texture_texture4 : enable\n"
641 "//#ifdef USESHADOWSAMPLER\n"
642 "//# extension GL_ARB_shadow : enable\n"
645 "//#ifdef __GLSL_CG_DATA_TYPES\n"
646 "//# define myhalf half\n"
647 "//# define myhalf2 half2\n"
648 "//# define myhalf3 half3\n"
649 "//# define myhalf4 half4\n"
651 "# define myhalf mediump float\n"
652 "# define myhalf2 mediump vec2\n"
653 "# define myhalf3 mediump vec3\n"
654 "# define myhalf4 mediump vec4\n"
657 "#ifdef VERTEX_SHADER\n"
658 "uniform highp mat4 ModelViewProjectionMatrix;\n"
661 "#ifdef MODE_DEPTH_OR_SHADOW\n"
662 "#ifdef VERTEX_SHADER\n"
665 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
668 "#else // !MODE_DEPTH_ORSHADOW\n"
673 "#ifdef MODE_SHOWDEPTH\n"
674 "#ifdef VERTEX_SHADER\n"
677 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
678 " VertexColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
682 "#ifdef FRAGMENT_SHADER\n"
685 " gl_FragColor = VertexColor;\n"
688 "#else // !MODE_SHOWDEPTH\n"
693 "#ifdef MODE_POSTPROCESS\n"
694 "varying mediump vec2 TexCoord1;\n"
695 "varying mediump vec2 TexCoord2;\n"
697 "#ifdef VERTEX_SHADER\n"
700 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
701 " TexCoord1 = Attrib_TexCoord0.xy;\n"
703 " TexCoord2 = Attrib_TexCoord4.xy;\n"
708 "#ifdef FRAGMENT_SHADER\n"
709 "uniform sampler2D Texture_First;\n"
711 "uniform sampler2D Texture_Second;\n"
712 "uniform lowp vec4 BloomColorSubtract;\n"
714 "#ifdef USEGAMMARAMPS\n"
715 "uniform sampler2D Texture_GammaRamps;\n"
717 "#ifdef USESATURATION\n"
718 "uniform lowp float Saturation;\n"
720 "#ifdef USEVIEWTINT\n"
721 "uniform lowp vec4 ViewTintColor;\n"
723 "//uncomment these if you want to use them:\n"
724 "uniform mediump vec4 UserVec1;\n"
725 "uniform mediump vec4 UserVec2;\n"
726 "// uniform mediump vec4 UserVec3;\n"
727 "// uniform mediump vec4 UserVec4;\n"
728 "// uniform highp float ClientTime;\n"
729 "uniform mediump vec2 PixelSize;\n"
732 " gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
734 " gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
736 "#ifdef USEVIEWTINT\n"
737 " gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
740 "#ifdef USEPOSTPROCESSING\n"
741 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
742 "// 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"
743 " float sobel = 1.0;\n"
744 " // vec2 ts = textureSize(Texture_First, 0);\n"
745 " // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
746 " vec2 px = PixelSize;\n"
747 " vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
748 " vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, 0.0)).rgb;\n"
749 " vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
750 " vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
751 " vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x, 0.0)).rgb;\n"
752 " vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
753 " vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
754 " vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2( 0.0,-px.y)).rgb;\n"
755 " vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
756 " vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
757 " vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2( 0.0, px.y)).rgb;\n"
758 " vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
759 " float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
760 " float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
761 " float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
762 " float px4 = 1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
763 " float px5 = 2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
764 " float px6 = 1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
765 " float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
766 " float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
767 " float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
768 " float py4 = 1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
769 " float py5 = 2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
770 " float py6 = 1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
771 " sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
772 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
773 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
774 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
775 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
776 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
777 " gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
778 " gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
781 "#ifdef USESATURATION\n"
782 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
783 " float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
784 " // 'vampire sight' effect, wheres red is compensated\n"
785 " #ifdef SATURATION_REDCOMPENSATE\n"
786 " float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
787 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
788 " gl_FragColor.r += rboost;\n"
790 " // normal desaturation\n"
791 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
792 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
796 "#ifdef USEGAMMARAMPS\n"
797 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
798 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
799 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
803 "#else // !MODE_POSTPROCESS\n"
808 "#ifdef MODE_GENERIC\n"
809 "#ifdef USEDIFFUSE\n"
810 "varying mediump vec2 TexCoord1;\n"
812 "#ifdef USESPECULAR\n"
813 "varying mediump vec2 TexCoord2;\n"
815 "#ifdef VERTEX_SHADER\n"
818 " VertexColor = Attrib_Color;\n"
819 "#ifdef USEDIFFUSE\n"
820 " TexCoord1 = Attrib_TexCoord0.xy;\n"
822 "#ifdef USESPECULAR\n"
823 " TexCoord2 = Attrib_TexCoord1.xy;\n"
825 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
829 "#ifdef FRAGMENT_SHADER\n"
830 "#ifdef USEDIFFUSE\n"
831 "uniform sampler2D Texture_First;\n"
833 "#ifdef USESPECULAR\n"
834 "uniform sampler2D Texture_Second;\n"
839 "#ifdef USEVIEWTINT\n"
840 " gl_FragColor = VertexColor;\n"
842 " gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
844 "#ifdef USEDIFFUSE\n"
845 " gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
848 "#ifdef USESPECULAR\n"
849 " vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
850 "# ifdef USECOLORMAPPING\n"
851 " gl_FragColor *= tex2;\n"
854 " gl_FragColor += tex2;\n"
856 "# ifdef USEVERTEXTEXTUREBLEND\n"
857 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
862 "#else // !MODE_GENERIC\n"
867 "#ifdef MODE_BLOOMBLUR\n"
868 "varying mediump vec2 TexCoord;\n"
869 "#ifdef VERTEX_SHADER\n"
872 " VertexColor = Attrib_Color;\n"
873 " TexCoord = Attrib_TexCoord0.xy;\n"
874 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
878 "#ifdef FRAGMENT_SHADER\n"
879 "uniform sampler2D Texture_First;\n"
880 "uniform mediump vec4 BloomBlur_Parameters;\n"
885 " vec2 tc = TexCoord;\n"
886 " vec3 color = texture2D(Texture_First, tc).rgb;\n"
887 " tc += BloomBlur_Parameters.xy;\n"
888 " for (i = 1;i < SAMPLES;i++)\n"
890 " color += texture2D(Texture_First, tc).rgb;\n"
891 " tc += BloomBlur_Parameters.xy;\n"
893 " gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
896 "#else // !MODE_BLOOMBLUR\n"
897 "#ifdef MODE_REFRACTION\n"
898 "varying mediump vec2 TexCoord;\n"
899 "varying highp vec4 ModelViewProjectionPosition;\n"
900 "uniform highp mat4 TexMatrix;\n"
901 "#ifdef VERTEX_SHADER\n"
905 " TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
906 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
907 " ModelViewProjectionPosition = gl_Position;\n"
911 "#ifdef FRAGMENT_SHADER\n"
912 "uniform sampler2D Texture_Normal;\n"
913 "uniform sampler2D Texture_Refraction;\n"
914 "uniform sampler2D Texture_Reflection;\n"
916 "uniform mediump vec4 DistortScaleRefractReflect;\n"
917 "uniform mediump vec4 ScreenScaleRefractReflect;\n"
918 "uniform mediump vec4 ScreenCenterRefractReflect;\n"
919 "uniform lowp vec4 RefractColor;\n"
920 "uniform lowp vec4 ReflectColor;\n"
921 "uniform mediump float ReflectFactor;\n"
922 "uniform mediump float ReflectOffset;\n"
926 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
927 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
928 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
929 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
930 " // FIXME temporary hack to detect the case that the reflection\n"
931 " // gets blackened at edges due to leaving the area that contains actual\n"
933 " // Remove this 'ack once we have a better way to stop this thing from\n"
935 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
936 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
937 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
938 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
939 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
940 " gl_FragColor = vec4(texture2D(Texture_Refraction, ScreenTexCoord).rgb, 1.0) * RefractColor;\n"
943 "#else // !MODE_REFRACTION\n"
948 "#ifdef MODE_WATER\n"
949 "varying mediump vec2 TexCoord;\n"
950 "varying highp vec3 EyeVector;\n"
951 "varying highp vec4 ModelViewProjectionPosition;\n"
952 "#ifdef VERTEX_SHADER\n"
953 "uniform highp vec3 EyePosition;\n"
954 "uniform highp mat4 TexMatrix;\n"
958 " TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
959 " vec3 EyeVectorModelSpace = EyePosition - Attrib_Position.xyz;\n"
960 " EyeVector.x = dot(EyeVectorModelSpace, Attrib_TexCoord1.xyz);\n"
961 " EyeVector.y = dot(EyeVectorModelSpace, Attrib_TexCoord2.xyz);\n"
962 " EyeVector.z = dot(EyeVectorModelSpace, Attrib_TexCoord3.xyz);\n"
963 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
964 " ModelViewProjectionPosition = gl_Position;\n"
968 "#ifdef FRAGMENT_SHADER\n"
969 "uniform sampler2D Texture_Normal;\n"
970 "uniform sampler2D Texture_Refraction;\n"
971 "uniform sampler2D Texture_Reflection;\n"
973 "uniform mediump vec4 DistortScaleRefractReflect;\n"
974 "uniform mediump vec4 ScreenScaleRefractReflect;\n"
975 "uniform mediump vec4 ScreenCenterRefractReflect;\n"
976 "uniform lowp vec4 RefractColor;\n"
977 "uniform lowp vec4 ReflectColor;\n"
978 "uniform mediump float ReflectFactor;\n"
979 "uniform mediump float ReflectOffset;\n"
980 "uniform highp float ClientTime;\n"
981 "#ifdef USENORMALMAPSCROLLBLEND\n"
982 "uniform highp vec2 NormalmapScrollBlend;\n"
987 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
988 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
989 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
990 " //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
991 " // slight water animation via 2 layer scrolling (todo: tweak)\n"
992 " #ifdef USENORMALMAPSCROLLBLEND\n"
993 " vec3 normal = texture2D(Texture_Normal, (TexCoord + vec2(0.08, 0.08)*ClientTime*NormalmapScrollBlend.x*0.5)*NormalmapScrollBlend.y).rgb - vec3(1.0);\n"
994 " normal += texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime*NormalmapScrollBlend.x)*NormalmapScrollBlend.y*0.75).rgb;\n"
995 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(normal) + vec3(0.15)).xyxy * DistortScaleRefractReflect;\n"
997 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
999 " // FIXME temporary hack to detect the case that the reflection\n"
1000 " // gets blackened at edges due to leaving the area that contains actual\n"
1002 " // Remove this 'ack once we have a better way to stop this thing from\n"
1004 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, 0.01)).rgb) / 0.002);\n"
1005 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, -0.01)).rgb) / 0.002);\n"
1006 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, 0.01)).rgb) / 0.002);\n"
1007 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, -0.01)).rgb) / 0.002);\n"
1008 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
1009 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, 0.005)).rgb) / 0.002);\n"
1010 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, -0.005)).rgb) / 0.002);\n"
1011 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, 0.005)).rgb) / 0.002);\n"
1012 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, -0.005)).rgb) / 0.002);\n"
1013 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
1014 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
1015 " gl_FragColor = mix(vec4(texture2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, vec4(texture2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
1018 "#else // !MODE_WATER\n"
1023 "// common definitions between vertex shader and fragment shader:\n"
1025 "varying mediump vec2 TexCoord;\n"
1026 "#ifdef USEVERTEXTEXTUREBLEND\n"
1027 "varying mediump vec2 TexCoord2;\n"
1029 "#ifdef USELIGHTMAP\n"
1030 "varying mediump vec2 TexCoordLightmap;\n"
1033 "#ifdef MODE_LIGHTSOURCE\n"
1034 "varying mediump vec3 CubeVector;\n"
1037 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
1038 "varying mediump vec3 LightVector;\n"
1041 "#ifdef USEEYEVECTOR\n"
1042 "varying highp vec3 EyeVector;\n"
1045 "varying highp vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
1048 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
1049 "varying lowp vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
1050 "varying lowp vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
1051 "varying lowp vec3 VectorR; // direction of R texcoord (surface normal)\n"
1054 "#ifdef USEREFLECTION\n"
1055 "varying highp vec4 ModelViewProjectionPosition;\n"
1057 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1058 "uniform highp vec3 LightPosition;\n"
1059 "varying highp vec4 ModelViewPosition;\n"
1062 "#ifdef MODE_LIGHTSOURCE\n"
1063 "uniform highp vec3 LightPosition;\n"
1065 "uniform highp vec3 EyePosition;\n"
1066 "#ifdef MODE_LIGHTDIRECTION\n"
1067 "uniform highp vec3 LightDir;\n"
1069 "uniform highp vec4 FogPlane;\n"
1071 "#ifdef USESHADOWMAPORTHO\n"
1072 "varying mediump vec3 ShadowMapTC;\n"
1075 "#ifdef USEBOUNCEGRID\n"
1076 "varying mediump vec3 BounceGridTexCoord;\n"
1084 "// 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"
1086 "// fragment shader specific:\n"
1087 "#ifdef FRAGMENT_SHADER\n"
1089 "uniform sampler2D Texture_Normal;\n"
1090 "uniform sampler2D Texture_Color;\n"
1091 "uniform sampler2D Texture_Gloss;\n"
1093 "uniform sampler2D Texture_Glow;\n"
1095 "#ifdef USEVERTEXTEXTUREBLEND\n"
1096 "uniform sampler2D Texture_SecondaryNormal;\n"
1097 "uniform sampler2D Texture_SecondaryColor;\n"
1098 "uniform sampler2D Texture_SecondaryGloss;\n"
1100 "uniform sampler2D Texture_SecondaryGlow;\n"
1103 "#ifdef USECOLORMAPPING\n"
1104 "uniform sampler2D Texture_Pants;\n"
1105 "uniform sampler2D Texture_Shirt;\n"
1108 "#ifdef USEFOGHEIGHTTEXTURE\n"
1109 "uniform sampler2D Texture_FogHeightTexture;\n"
1111 "uniform sampler2D Texture_FogMask;\n"
1113 "#ifdef USELIGHTMAP\n"
1114 "uniform sampler2D Texture_Lightmap;\n"
1116 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1117 "uniform sampler2D Texture_Deluxemap;\n"
1119 "#ifdef USEREFLECTION\n"
1120 "uniform sampler2D Texture_Reflection;\n"
1123 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1124 "uniform sampler2D Texture_ScreenDepth;\n"
1125 "uniform sampler2D Texture_ScreenNormalMap;\n"
1127 "#ifdef USEDEFERREDLIGHTMAP\n"
1128 "uniform sampler2D Texture_ScreenDiffuse;\n"
1129 "uniform sampler2D Texture_ScreenSpecular;\n"
1132 "uniform lowp vec3 Color_Pants;\n"
1133 "uniform lowp vec3 Color_Shirt;\n"
1134 "uniform lowp vec3 FogColor;\n"
1137 "uniform highp float FogRangeRecip;\n"
1138 "uniform highp float FogPlaneViewDist;\n"
1139 "uniform highp float FogHeightFade;\n"
1140 "vec3 FogVertex(vec3 surfacecolor)\n"
1142 " vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1143 " float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1145 "#ifdef USEFOGHEIGHTTEXTURE\n"
1146 " vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1147 " fogfrac = fogheightpixel.a;\n"
1148 " return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1150 "# ifdef USEFOGOUTSIDE\n"
1151 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1153 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1155 " return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1160 "#ifdef USEOFFSETMAPPING\n"
1161 "uniform mediump float OffsetMapping_Scale;\n"
1162 "vec2 OffsetMapping(vec2 TexCoord)\n"
1164 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1165 " // 14 sample relief mapping: linear search and then binary search\n"
1166 " // this basically steps forward a small amount repeatedly until it finds\n"
1167 " // itself inside solid, then jitters forward and back using decreasing\n"
1168 " // amounts to find the impact\n"
1169 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1170 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1171 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1172 " vec3 RT = vec3(TexCoord, 1);\n"
1173 " OffsetVector *= 0.1;\n"
1174 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1175 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1176 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1177 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1178 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1179 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1180 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1181 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1182 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1183 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
1184 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
1185 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
1186 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
1187 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1190 " // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1191 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1192 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1193 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1194 " OffsetVector *= 0.5;\n"
1195 " TexCoord += OffsetVector * (1.0 - texture2D(Texture_Normal, TexCoord).a);\n"
1196 " TexCoord += OffsetVector * (1.0 - texture2D(Texture_Normal, TexCoord).a);\n"
1197 " return TexCoord;\n"
1200 "#endif // USEOFFSETMAPPING\n"
1202 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1203 "uniform sampler2D Texture_Attenuation;\n"
1204 "uniform samplerCube Texture_Cube;\n"
1207 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1209 "#ifdef USESHADOWMAP2D\n"
1210 "# ifdef USESHADOWSAMPLER\n"
1211 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1213 "uniform sampler2D Texture_ShadowMap2D;\n"
1217 "#ifdef USESHADOWMAPVSDCT\n"
1218 "uniform samplerCube Texture_CubeProjection;\n"
1221 "#if defined(USESHADOWMAP2D)\n"
1222 "uniform mediump vec2 ShadowMap_TextureScale;\n"
1223 "uniform mediump vec4 ShadowMap_Parameters;\n"
1226 "#if defined(USESHADOWMAP2D)\n"
1227 "# ifdef USESHADOWMAPORTHO\n"
1228 "# define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1230 "# ifdef USESHADOWMAPVSDCT\n"
1231 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1233 " vec3 adir = abs(dir);\n"
1234 " vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1235 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1236 " return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1239 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1241 " vec3 adir = abs(dir);\n"
1242 " float ma = adir.z;\n"
1243 " vec4 proj = vec4(dir, 2.5);\n"
1244 " if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1245 " if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1246 " vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1247 " 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"
1251 "#endif // defined(USESHADOWMAP2D)\n"
1253 "# ifdef USESHADOWMAP2D\n"
1254 "float ShadowMapCompare(vec3 dir)\n"
1256 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1259 "# ifdef USESHADOWSAMPLER\n"
1260 "# ifdef USESHADOWMAPPCF\n"
1261 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1262 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1263 " 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"
1265 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1268 "# ifdef USESHADOWMAPPCF\n"
1269 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1270 "# ifdef GL_ARB_texture_gather\n"
1271 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1273 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1275 " vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1276 "# if USESHADOWMAPPCF > 1\n"
1277 " vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1278 " vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1279 " vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1280 " vec4 group4 = step(shadowmaptc.z, texval(-2.0, 0.0));\n"
1281 " vec4 group5 = step(shadowmaptc.z, texval( 0.0, 0.0));\n"
1282 " vec4 group6 = step(shadowmaptc.z, texval( 2.0, 0.0));\n"
1283 " vec4 group7 = step(shadowmaptc.z, texval(-2.0, 2.0));\n"
1284 " vec4 group8 = step(shadowmaptc.z, texval( 0.0, 2.0));\n"
1285 " vec4 group9 = step(shadowmaptc.z, texval( 2.0, 2.0));\n"
1286 " vec4 locols = vec4(group1.ab, group3.ab);\n"
1287 " vec4 hicols = vec4(group7.rg, group9.rg);\n"
1288 " locols.yz += group2.ab;\n"
1289 " hicols.yz += group8.rg;\n"
1290 " vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1291 " vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1292 " mix(locols, hicols, offset.y);\n"
1293 " vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1294 " cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1295 " f = dot(cols, vec4(1.0/25.0));\n"
1297 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1298 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1299 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1300 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1301 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1302 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1303 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1306 "# ifdef GL_EXT_gpu_shader4\n"
1307 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1309 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1311 "# if USESHADOWMAPPCF > 1\n"
1312 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1313 " center *= ShadowMap_TextureScale;\n"
1314 " 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"
1315 " 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"
1316 " 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"
1317 " 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"
1318 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1319 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1321 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1322 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1323 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1324 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1325 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1326 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1330 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1333 "# ifdef USESHADOWMAPORTHO\n"
1334 " return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1340 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1341 "#endif // FRAGMENT_SHADER\n"
1346 "#ifdef MODE_DEFERREDGEOMETRY\n"
1347 "#ifdef VERTEX_SHADER\n"
1348 "uniform highp mat4 TexMatrix;\n"
1349 "#ifdef USEVERTEXTEXTUREBLEND\n"
1350 "uniform highp mat4 BackgroundTexMatrix;\n"
1352 "uniform highp mat4 ModelViewMatrix;\n"
1355 " TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
1356 "#ifdef USEVERTEXTEXTUREBLEND\n"
1357 " VertexColor = Attrib_Color;\n"
1358 " TexCoord2 = vec2(BackgroundTexMatrix * Attrib_TexCoord0);\n"
1361 " // transform unnormalized eye direction into tangent space\n"
1362 "#ifdef USEOFFSETMAPPING\n"
1363 " vec3 EyeVectorModelSpace = EyePosition - Attrib_Position.xyz;\n"
1364 " EyeVector.x = dot(EyeVectorModelSpace, Attrib_TexCoord1.xyz);\n"
1365 " EyeVector.y = dot(EyeVectorModelSpace, Attrib_TexCoord2.xyz);\n"
1366 " EyeVector.z = dot(EyeVectorModelSpace, Attrib_TexCoord3.xyz);\n"
1369 " VectorS = (ModelViewMatrix * vec4(Attrib_TexCoord1.xyz, 0)).xyz;\n"
1370 " VectorT = (ModelViewMatrix * vec4(Attrib_TexCoord2.xyz, 0)).xyz;\n"
1371 " VectorR = (ModelViewMatrix * vec4(Attrib_TexCoord3.xyz, 0)).xyz;\n"
1372 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1374 "#endif // VERTEX_SHADER\n"
1376 "#ifdef FRAGMENT_SHADER\n"
1379 "#ifdef USEOFFSETMAPPING\n"
1380 " // apply offsetmapping\n"
1381 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1382 "#define TexCoord TexCoordOffset\n"
1385 "#ifdef USEALPHAKILL\n"
1386 " if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1390 "#ifdef USEVERTEXTEXTUREBLEND\n"
1391 " float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1392 " float terrainblend = clamp(float(VertexColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1393 " //float terrainblend = min(float(VertexColor.a) * alpha * 2.0, float(1.0));\n"
1394 " //float terrainblend = float(VertexColor.a) * alpha > 0.5;\n"
1397 "#ifdef USEVERTEXTEXTUREBLEND\n"
1398 " vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1399 " float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1401 " vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1402 " float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1405 " gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1407 "#endif // FRAGMENT_SHADER\n"
1408 "#else // !MODE_DEFERREDGEOMETRY\n"
1413 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1414 "#ifdef VERTEX_SHADER\n"
1415 "uniform highp mat4 ModelViewMatrix;\n"
1418 " ModelViewPosition = ModelViewMatrix * Attrib_Position;\n"
1419 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1421 "#endif // VERTEX_SHADER\n"
1423 "#ifdef FRAGMENT_SHADER\n"
1424 "uniform highp mat4 ViewToLight;\n"
1425 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1426 "uniform highp vec2 ScreenToDepth;\n"
1427 "uniform myhalf3 DeferredColor_Ambient;\n"
1428 "uniform myhalf3 DeferredColor_Diffuse;\n"
1429 "#ifdef USESPECULAR\n"
1430 "uniform myhalf3 DeferredColor_Specular;\n"
1431 "uniform myhalf SpecularPower;\n"
1433 "uniform myhalf2 PixelToScreenTexCoord;\n"
1436 " // calculate viewspace pixel position\n"
1437 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1439 " position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1440 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1441 " // decode viewspace pixel normal\n"
1442 " myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1443 " myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1444 " // surfacenormal = pixel normal in viewspace\n"
1445 " // LightVector = pixel to light in viewspace\n"
1446 " // CubeVector = position in lightspace\n"
1447 " // eyevector = pixel to view in viewspace\n"
1448 " vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1449 " myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1450 "#ifdef USEDIFFUSE\n"
1451 " // calculate diffuse shading\n"
1452 " myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1453 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1455 "#ifdef USESPECULAR\n"
1456 " // calculate directional shading\n"
1457 " vec3 eyevector = position * -1.0;\n"
1458 "# ifdef USEEXACTSPECULARMATH\n"
1459 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1461 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1462 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1466 "#if defined(USESHADOWMAP2D)\n"
1467 " fade *= ShadowMapCompare(CubeVector);\n"
1470 "#ifdef USEDIFFUSE\n"
1471 " gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1473 " gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1475 "#ifdef USESPECULAR\n"
1476 " gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1478 " gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1481 "# ifdef USECUBEFILTER\n"
1482 " vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1483 " gl_FragData[0].rgb *= cubecolor;\n"
1484 " gl_FragData[1].rgb *= cubecolor;\n"
1487 "#endif // FRAGMENT_SHADER\n"
1488 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1493 "#ifdef VERTEX_SHADER\n"
1494 "uniform highp mat4 TexMatrix;\n"
1495 "#ifdef USEVERTEXTEXTUREBLEND\n"
1496 "uniform highp mat4 BackgroundTexMatrix;\n"
1498 "#ifdef MODE_LIGHTSOURCE\n"
1499 "uniform highp mat4 ModelToLight;\n"
1501 "#ifdef USESHADOWMAPORTHO\n"
1502 "uniform highp mat4 ShadowMapMatrix;\n"
1504 "#ifdef USEBOUNCEGRID\n"
1505 "uniform highp mat4 BounceGridMatrix;\n"
1509 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1510 " VertexColor = Attrib_Color;\n"
1512 " // copy the surface texcoord\n"
1513 " TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
1514 "#ifdef USEVERTEXTEXTUREBLEND\n"
1515 " TexCoord2 = vec2(BackgroundTexMatrix * Attrib_TexCoord0);\n"
1517 "#ifdef USELIGHTMAP\n"
1518 " TexCoordLightmap = vec2(Attrib_TexCoord4);\n"
1521 "#ifdef USEBOUNCEGRID\n"
1522 " BounceGridTexCoord = vec3(BounceGridMatrix * Attrib_Position);\n"
1525 "#ifdef MODE_LIGHTSOURCE\n"
1526 " // transform vertex position into light attenuation/cubemap space\n"
1527 " // (-1 to +1 across the light box)\n"
1528 " CubeVector = vec3(ModelToLight * Attrib_Position);\n"
1530 "# ifdef USEDIFFUSE\n"
1531 " // transform unnormalized light direction into tangent space\n"
1532 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
1533 " // normalize it per pixel)\n"
1534 " vec3 lightminusvertex = LightPosition - Attrib_Position.xyz;\n"
1535 " LightVector.x = dot(lightminusvertex, Attrib_TexCoord1.xyz);\n"
1536 " LightVector.y = dot(lightminusvertex, Attrib_TexCoord2.xyz);\n"
1537 " LightVector.z = dot(lightminusvertex, Attrib_TexCoord3.xyz);\n"
1541 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1542 " LightVector.x = dot(LightDir, Attrib_TexCoord1.xyz);\n"
1543 " LightVector.y = dot(LightDir, Attrib_TexCoord2.xyz);\n"
1544 " LightVector.z = dot(LightDir, Attrib_TexCoord3.xyz);\n"
1547 " // transform unnormalized eye direction into tangent space\n"
1548 "#ifdef USEEYEVECTOR\n"
1549 " vec3 EyeVectorModelSpace = EyePosition - Attrib_Position.xyz;\n"
1550 " EyeVector.x = dot(EyeVectorModelSpace, Attrib_TexCoord1.xyz);\n"
1551 " EyeVector.y = dot(EyeVectorModelSpace, Attrib_TexCoord2.xyz);\n"
1552 " EyeVector.z = dot(EyeVectorModelSpace, Attrib_TexCoord3.xyz);\n"
1556 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - Attrib_Position.xyz;\n"
1557 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, Attrib_Position);\n"
1560 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1561 " VectorS = Attrib_TexCoord1.xyz;\n"
1562 " VectorT = Attrib_TexCoord2.xyz;\n"
1563 " VectorR = Attrib_TexCoord3.xyz;\n"
1566 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1567 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1569 "#ifdef USESHADOWMAPORTHO\n"
1570 " ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1573 "#ifdef USEREFLECTION\n"
1574 " ModelViewProjectionPosition = gl_Position;\n"
1577 "#endif // VERTEX_SHADER\n"
1582 "#ifdef FRAGMENT_SHADER\n"
1583 "#ifdef USEDEFERREDLIGHTMAP\n"
1584 "uniform myhalf2 PixelToScreenTexCoord;\n"
1585 "uniform myhalf3 DeferredMod_Diffuse;\n"
1586 "uniform myhalf3 DeferredMod_Specular;\n"
1588 "uniform myhalf3 Color_Ambient;\n"
1589 "uniform myhalf3 Color_Diffuse;\n"
1590 "uniform myhalf3 Color_Specular;\n"
1591 "uniform myhalf SpecularPower;\n"
1593 "uniform myhalf3 Color_Glow;\n"
1595 "uniform myhalf Alpha;\n"
1596 "#ifdef USEREFLECTION\n"
1597 "uniform mediump vec4 DistortScaleRefractReflect;\n"
1598 "uniform mediump vec4 ScreenScaleRefractReflect;\n"
1599 "uniform mediump vec4 ScreenCenterRefractReflect;\n"
1600 "uniform lowp vec4 ReflectColor;\n"
1602 "#ifdef USEREFLECTCUBE\n"
1603 "uniform highp mat4 ModelToReflectCube;\n"
1604 "uniform sampler2D Texture_ReflectMask;\n"
1605 "uniform samplerCube Texture_ReflectCube;\n"
1607 "#ifdef MODE_LIGHTDIRECTION\n"
1608 "uniform myhalf3 LightColor;\n"
1610 "#ifdef MODE_LIGHTSOURCE\n"
1611 "uniform myhalf3 LightColor;\n"
1613 "#ifdef USEBOUNCEGRID\n"
1614 "uniform sampler3D Texture_BounceGrid;\n"
1615 "uniform float BounceGridIntensity;\n"
1619 "#ifdef USEOFFSETMAPPING\n"
1620 " // apply offsetmapping\n"
1621 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1622 "#define TexCoord TexCoordOffset\n"
1625 " // combine the diffuse textures (base, pants, shirt)\n"
1626 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1627 "#ifdef USEALPHAKILL\n"
1628 " if (color.a < 0.5)\n"
1631 " color.a *= Alpha;\n"
1632 "#ifdef USECOLORMAPPING\n"
1633 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1635 "#ifdef USEVERTEXTEXTUREBLEND\n"
1636 " myhalf terrainblend = clamp(myhalf(VertexColor.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1637 " //myhalf terrainblend = min(myhalf(VertexColor.a) * color.a * 2.0, myhalf(1.0));\n"
1638 " //myhalf terrainblend = myhalf(VertexColor.a) * color.a > 0.5;\n"
1639 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1641 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1644 " // get the surface normal\n"
1645 "#ifdef USEVERTEXTEXTUREBLEND\n"
1646 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1648 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1651 " // get the material colors\n"
1652 " myhalf3 diffusetex = color.rgb;\n"
1653 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1654 "# ifdef USEVERTEXTEXTUREBLEND\n"
1655 " myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1657 " myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1661 "#ifdef USEREFLECTCUBE\n"
1662 " vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1663 " vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1664 " vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1665 " diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1671 "#ifdef MODE_LIGHTSOURCE\n"
1672 " // light source\n"
1673 "#ifdef USEDIFFUSE\n"
1674 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1675 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1676 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1677 "#ifdef USESPECULAR\n"
1678 "#ifdef USEEXACTSPECULARMATH\n"
1679 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1681 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1682 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1684 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1687 " color.rgb = diffusetex * Color_Ambient;\n"
1689 " color.rgb *= LightColor;\n"
1690 " color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1691 "#if defined(USESHADOWMAP2D)\n"
1692 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1694 "# ifdef USECUBEFILTER\n"
1695 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1697 "#endif // MODE_LIGHTSOURCE\n"
1702 "#ifdef MODE_LIGHTDIRECTION\n"
1704 "#ifdef USEDIFFUSE\n"
1705 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1707 "#define lightcolor LightColor\n"
1708 "#endif // MODE_LIGHTDIRECTION\n"
1709 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1711 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1712 " myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1713 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1714 " // convert modelspace light vector to tangentspace\n"
1715 " myhalf3 lightnormal;\n"
1716 " lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1717 " lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1718 " lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1719 " lightnormal = normalize(lightnormal); // VectorS/T/R are not always perfectly normalized, and EXACTSPECULARMATH is very picky about this\n"
1720 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1721 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1722 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1723 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1724 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1725 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1726 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1727 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1728 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1729 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1730 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1731 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1733 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1734 " myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1735 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1741 "#ifdef MODE_FAKELIGHT\n"
1743 "myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
1744 "myhalf3 lightcolor = myhalf3(1.0);\n"
1745 "#endif // MODE_FAKELIGHT\n"
1750 "#ifdef MODE_LIGHTMAP\n"
1751 " color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1752 "#endif // MODE_LIGHTMAP\n"
1753 "#ifdef MODE_VERTEXCOLOR\n"
1754 " color.rgb = diffusetex * (Color_Ambient + myhalf3(VertexColor.rgb) * Color_Diffuse);\n"
1755 "#endif // MODE_VERTEXCOLOR\n"
1756 "#ifdef MODE_FLATCOLOR\n"
1757 " color.rgb = diffusetex * Color_Ambient;\n"
1758 "#endif // MODE_FLATCOLOR\n"
1764 "# ifdef USEDIFFUSE\n"
1765 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1766 "# ifdef USESPECULAR\n"
1767 "# ifdef USEEXACTSPECULARMATH\n"
1768 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1770 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1771 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1773 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1775 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1778 " color.rgb = diffusetex * Color_Ambient;\n"
1782 "#ifdef USESHADOWMAPORTHO\n"
1783 " color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1786 "#ifdef USEDEFERREDLIGHTMAP\n"
1787 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1788 " color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1789 " color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1792 "#ifdef USEBOUNCEGRID\n"
1793 " color.rgb += diffusetex * myhalf3(texture3D(Texture_BounceGrid, BounceGridTexCoord)) * BounceGridIntensity;\n"
1797 "#ifdef USEVERTEXTEXTUREBLEND\n"
1798 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1800 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1805 " color.rgb = FogVertex(color.rgb);\n"
1808 " // 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"
1809 "#ifdef USEREFLECTION\n"
1810 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1811 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1812 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1813 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1814 " // FIXME temporary hack to detect the case that the reflection\n"
1815 " // gets blackened at edges due to leaving the area that contains actual\n"
1817 " // Remove this 'ack once we have a better way to stop this thing from\n"
1819 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1820 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1821 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1822 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1823 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1824 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1827 " gl_FragColor = vec4(color);\n"
1829 "#endif // FRAGMENT_SHADER\n"
1831 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1832 "#endif // !MODE_DEFERREDGEOMETRY\n"
1833 "#endif // !MODE_WATER\n"
1834 "#endif // !MODE_REFRACTION\n"
1835 "#endif // !MODE_BLOOMBLUR\n"
1836 "#endif // !MODE_GENERIC\n"
1837 "#endif // !MODE_POSTPROCESS\n"
1838 "#endif // !MODE_SHOWDEPTH\n"
1839 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1843 =========================================================================================================================================================
1847 =========================================================================================================================================================
1851 =========================================================================================================================================================
1855 =========================================================================================================================================================
1859 =========================================================================================================================================================
1863 =========================================================================================================================================================
1867 =========================================================================================================================================================
1870 const char *builtinhlslshaderstring =
1871 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1872 "// written by Forest 'LordHavoc' Hale\n"
1873 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1875 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1876 "#if defined(USEREFLECTION)\n"
1877 "#undef USESHADOWMAPORTHO\n"
1880 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1883 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1884 "#define USELIGHTMAP\n"
1886 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
1887 "#define USEEYEVECTOR\n"
1890 "#ifdef FRAGMENT_SHADER\n"
1892 "//#undef USESHADOWMAPPCF\n"
1893 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1894 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1896 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1900 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1901 "#ifdef VERTEX_SHADER\n"
1904 "float4 gl_Vertex : POSITION,\n"
1905 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1906 "out float4 gl_Position : POSITION,\n"
1907 "out float Depth : TEXCOORD0\n"
1910 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1911 " Depth = gl_Position.z;\n"
1915 "#ifdef FRAGMENT_SHADER\n"
1918 "float Depth : TEXCOORD0,\n"
1919 "out float4 gl_FragColor : COLOR\n"
1922 "// float4 temp = float4(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0),0.0);\n"
1923 " float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
1924 " temp.yz -= floor(temp.yz);\n"
1925 " gl_FragColor = temp;\n"
1926 "// gl_FragColor = float4(Depth,0,0,0);\n"
1929 "#else // !MODE_DEPTH_ORSHADOW\n"
1934 "#ifdef MODE_SHOWDEPTH\n"
1935 "#ifdef VERTEX_SHADER\n"
1938 "float4 gl_Vertex : POSITION,\n"
1939 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1940 "out float4 gl_Position : POSITION,\n"
1941 "out float4 gl_FrontColor : COLOR0\n"
1944 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1945 " gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1949 "#ifdef FRAGMENT_SHADER\n"
1952 "float4 gl_FrontColor : COLOR0,\n"
1953 "out float4 gl_FragColor : COLOR\n"
1956 " gl_FragColor = gl_FrontColor;\n"
1959 "#else // !MODE_SHOWDEPTH\n"
1964 "#ifdef MODE_POSTPROCESS\n"
1966 "#ifdef VERTEX_SHADER\n"
1969 "float4 gl_Vertex : POSITION,\n"
1970 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1971 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1972 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1973 "out float4 gl_Position : POSITION,\n"
1974 "out float2 TexCoord1 : TEXCOORD0,\n"
1975 "out float2 TexCoord2 : TEXCOORD1\n"
1978 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1979 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
1981 " TexCoord2 = gl_MultiTexCoord4.xy;\n"
1986 "#ifdef FRAGMENT_SHADER\n"
1989 "float2 TexCoord1 : TEXCOORD0,\n"
1990 "float2 TexCoord2 : TEXCOORD1,\n"
1991 "uniform sampler Texture_First : register(s0),\n"
1993 "uniform sampler Texture_Second : register(s1),\n"
1995 "#ifdef USEGAMMARAMPS\n"
1996 "uniform sampler Texture_GammaRamps : register(s2),\n"
1998 "#ifdef USESATURATION\n"
1999 "uniform float Saturation : register(c30),\n"
2001 "#ifdef USEVIEWTINT\n"
2002 "uniform float4 ViewTintColor : register(c41),\n"
2004 "uniform float4 UserVec1 : register(c37),\n"
2005 "uniform float4 UserVec2 : register(c38),\n"
2006 "uniform float4 UserVec3 : register(c39),\n"
2007 "uniform float4 UserVec4 : register(c40),\n"
2008 "uniform float ClientTime : register(c2),\n"
2009 "uniform float2 PixelSize : register(c25),\n"
2010 "uniform float4 BloomColorSubtract : register(c43),\n"
2011 "out float4 gl_FragColor : COLOR\n"
2014 " gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
2016 " gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
2018 "#ifdef USEVIEWTINT\n"
2019 " gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
2022 "#ifdef USEPOSTPROCESSING\n"
2023 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
2024 "// 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"
2025 " float sobel = 1.0;\n"
2026 " // float2 ts = textureSize(Texture_First, 0);\n"
2027 " // float2 px = float2(1/ts.x, 1/ts.y);\n"
2028 " float2 px = PixelSize;\n"
2029 " float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2030 " float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x, 0.0)).rgb;\n"
2031 " float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2032 " float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2033 " float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x, 0.0)).rgb;\n"
2034 " float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2035 " float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2036 " float3 y2 = tex2D(Texture_First, TexCoord1 + float2( 0.0,-px.y)).rgb;\n"
2037 " float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2038 " float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2039 " float3 y5 = tex2D(Texture_First, TexCoord1 + float2( 0.0, px.y)).rgb;\n"
2040 " float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2041 " float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
2042 " float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
2043 " float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
2044 " float px4 = 1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
2045 " float px5 = 2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
2046 " float px6 = 1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
2047 " float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
2048 " float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
2049 " float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
2050 " float py4 = 1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
2051 " float py5 = 2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
2052 " float py6 = 1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
2053 " sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
2054 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2055 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2056 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2057 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107, 0.707107)) * UserVec1.y;\n"
2058 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990, 0.891007)) * UserVec1.y;\n"
2059 " gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2060 " gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2063 "#ifdef USESATURATION\n"
2064 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2065 " float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2066 " // 'vampire sight' effect, wheres red is compensated\n"
2067 " #ifdef SATURATION_REDCOMPENSATE\n"
2068 " float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
2069 " gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2070 " gl_FragColor.r += r;\n"
2072 " // normal desaturation\n"
2073 " //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2074 " gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2078 "#ifdef USEGAMMARAMPS\n"
2079 " gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2080 " gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2081 " gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2085 "#else // !MODE_POSTPROCESS\n"
2090 "#ifdef MODE_GENERIC\n"
2091 "#ifdef VERTEX_SHADER\n"
2094 "float4 gl_Vertex : POSITION,\n"
2095 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2096 "float4 gl_Color : COLOR0,\n"
2097 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2098 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2099 "out float4 gl_Position : POSITION,\n"
2100 "#ifdef USEDIFFUSE\n"
2101 "out float2 TexCoord1 : TEXCOORD0,\n"
2103 "#ifdef USESPECULAR\n"
2104 "out float2 TexCoord2 : TEXCOORD1,\n"
2106 "out float4 gl_FrontColor : COLOR\n"
2110 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2112 " gl_FrontColor = gl_Color; // Cg is forward\n"
2114 "#ifdef USEDIFFUSE\n"
2115 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
2117 "#ifdef USESPECULAR\n"
2118 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
2120 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2124 "#ifdef FRAGMENT_SHADER\n"
2128 "float4 gl_FrontColor : COLOR0,\n"
2129 "float2 TexCoord1 : TEXCOORD0,\n"
2130 "float2 TexCoord2 : TEXCOORD1,\n"
2131 "#ifdef USEDIFFUSE\n"
2132 "uniform sampler Texture_First : register(s0),\n"
2134 "#ifdef USESPECULAR\n"
2135 "uniform sampler Texture_Second : register(s1),\n"
2137 "out float4 gl_FragColor : COLOR\n"
2140 "#ifdef USEVIEWTINT\n"
2141 " gl_FragColor = gl_FrontColor;\n"
2143 " gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
2145 "#ifdef USEDIFFUSE\n"
2146 " gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2149 "#ifdef USESPECULAR\n"
2150 " float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2151 "# ifdef USECOLORMAPPING\n"
2152 " gl_FragColor *= tex2;\n"
2155 " gl_FragColor += tex2;\n"
2157 "# ifdef USEVERTEXTEXTUREBLEND\n"
2158 " gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2163 "#else // !MODE_GENERIC\n"
2168 "#ifdef MODE_BLOOMBLUR\n"
2169 "#ifdef VERTEX_SHADER\n"
2172 "float4 gl_Vertex : POSITION,\n"
2173 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2174 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2175 "out float4 gl_Position : POSITION,\n"
2176 "out float2 TexCoord : TEXCOORD0\n"
2179 " TexCoord = gl_MultiTexCoord0.xy;\n"
2180 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2184 "#ifdef FRAGMENT_SHADER\n"
2188 "float2 TexCoord : TEXCOORD0,\n"
2189 "uniform sampler Texture_First : register(s0),\n"
2190 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2191 "out float4 gl_FragColor : COLOR\n"
2195 " float2 tc = TexCoord;\n"
2196 " float3 color = tex2D(Texture_First, tc).rgb;\n"
2197 " tc += BloomBlur_Parameters.xy;\n"
2198 " for (i = 1;i < SAMPLES;i++)\n"
2200 " color += tex2D(Texture_First, tc).rgb;\n"
2201 " tc += BloomBlur_Parameters.xy;\n"
2203 " gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2206 "#else // !MODE_BLOOMBLUR\n"
2207 "#ifdef MODE_REFRACTION\n"
2208 "#ifdef VERTEX_SHADER\n"
2211 "float4 gl_Vertex : POSITION,\n"
2212 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2213 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2214 "uniform float4x4 TexMatrix : register(c0),\n"
2215 "uniform float3 EyePosition : register(c24),\n"
2216 "out float4 gl_Position : POSITION,\n"
2217 "out float2 TexCoord : TEXCOORD0,\n"
2218 "out float3 EyeVector : TEXCOORD1,\n"
2219 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2222 " TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2223 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2224 " ModelViewProjectionPosition = gl_Position;\n"
2228 "#ifdef FRAGMENT_SHADER\n"
2231 "float2 TexCoord : TEXCOORD0,\n"
2232 "float3 EyeVector : TEXCOORD1,\n"
2233 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2234 "uniform sampler Texture_Normal : register(s0),\n"
2235 "uniform sampler Texture_Refraction : register(s3),\n"
2236 "uniform sampler Texture_Reflection : register(s7),\n"
2237 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2238 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2239 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2240 "uniform float4 RefractColor : register(c29),\n"
2241 "out float4 gl_FragColor : COLOR\n"
2244 " float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2245 " //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"
2246 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2247 " float2 ScreenTexCoord = SafeScreenTexCoord + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy;\n"
2248 " // FIXME temporary hack to detect the case that the reflection\n"
2249 " // gets blackened at edges due to leaving the area that contains actual\n"
2251 " // Remove this 'ack once we have a better way to stop this thing from\n"
2253 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2254 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2255 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2256 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2257 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2258 " gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
2261 "#else // !MODE_REFRACTION\n"
2266 "#ifdef MODE_WATER\n"
2267 "#ifdef VERTEX_SHADER\n"
2271 "float4 gl_Vertex : POSITION,\n"
2272 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2273 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2274 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2275 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2276 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2277 "uniform float4x4 TexMatrix : register(c0),\n"
2278 "uniform float3 EyePosition : register(c24),\n"
2279 "out float4 gl_Position : POSITION,\n"
2280 "out float2 TexCoord : TEXCOORD0,\n"
2281 "out float3 EyeVector : TEXCOORD1,\n"
2282 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2285 " TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2286 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2287 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2288 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2289 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2290 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2291 " ModelViewProjectionPosition = gl_Position;\n"
2295 "#ifdef FRAGMENT_SHADER\n"
2298 "float2 TexCoord : TEXCOORD0,\n"
2299 "float3 EyeVector : TEXCOORD1,\n"
2300 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2301 "uniform sampler Texture_Normal : register(s0),\n"
2302 "uniform sampler Texture_Refraction : register(s3),\n"
2303 "uniform sampler Texture_Reflection : register(s7),\n"
2304 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2305 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2306 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2307 "uniform float4 RefractColor : register(c29),\n"
2308 "uniform float4 ReflectColor : register(c26),\n"
2309 "uniform float ReflectFactor : register(c27),\n"
2310 "uniform float ReflectOffset : register(c28),\n"
2311 "out float4 gl_FragColor : COLOR\n"
2314 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2315 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2316 " float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2317 " //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2318 " float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2319 " // FIXME temporary hack to detect the case that the reflection\n"
2320 " // gets blackened at edges due to leaving the area that contains actual\n"
2322 " // Remove this 'ack once we have a better way to stop this thing from\n"
2324 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2325 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2326 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2327 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2328 " ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2329 " f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2330 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2331 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2332 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2333 " ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2334 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2335 " gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
2338 "#else // !MODE_WATER\n"
2343 "// 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"
2345 "// fragment shader specific:\n"
2346 "#ifdef FRAGMENT_SHADER\n"
2349 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2352 "#ifdef USEFOGHEIGHTTEXTURE\n"
2353 " float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2354 " fogfrac = fogheightpixel.a;\n"
2355 " return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2357 "# ifdef USEFOGOUTSIDE\n"
2358 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2360 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2362 " return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2367 "#ifdef USEOFFSETMAPPING\n"
2368 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2370 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2371 " // 14 sample relief mapping: linear search and then binary search\n"
2372 " // this basically steps forward a small amount repeatedly until it finds\n"
2373 " // itself inside solid, then jitters forward and back using decreasing\n"
2374 " // amounts to find the impact\n"
2375 " //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2376 " //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2377 " float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2378 " float3 RT = float3(TexCoord, 1);\n"
2379 " OffsetVector *= 0.1;\n"
2380 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2381 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2382 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2383 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2384 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2385 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2386 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2387 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2388 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2389 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
2390 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
2391 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
2392 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
2393 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2396 " // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2397 " //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2398 " //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2399 " float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2400 " OffsetVector *= 0.5;\n"
2401 " TexCoord += OffsetVector * (1.0 - tex2D(Texture_Normal, TexCoord).a);\n"
2402 " TexCoord += OffsetVector * (1.0 - tex2D(Texture_Normal, TexCoord).a);\n"
2403 " return TexCoord;\n"
2406 "#endif // USEOFFSETMAPPING\n"
2408 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2409 "#if defined(USESHADOWMAP2D)\n"
2410 "# ifdef USESHADOWMAPORTHO\n"
2411 "# define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2413 "# ifdef USESHADOWMAPVSDCT\n"
2414 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2416 " float3 adir = abs(dir);\n"
2417 " float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2418 " float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2419 " return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2422 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2424 " float3 adir = abs(dir);\n"
2425 " float ma = adir.z;\n"
2426 " float4 proj = float4(dir, 2.5);\n"
2427 " if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2428 " if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2430 " 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"
2432 " float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2433 " 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"
2438 "#endif // defined(USESHADOWMAP2D)\n"
2440 "# ifdef USESHADOWMAP2D\n"
2441 "#ifdef USESHADOWMAPVSDCT\n"
2442 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2444 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2447 "#ifdef USESHADOWMAPVSDCT\n"
2448 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2450 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2454 "# ifdef USESHADOWSAMPLER\n"
2455 "# ifdef USESHADOWMAPPCF\n"
2456 "# define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r \n"
2457 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2458 " 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"
2460 " f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2463 "# ifdef USESHADOWMAPPCF\n"
2464 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2465 "# ifdef GL_ARB_texture_gather\n"
2466 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2468 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2470 " float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2471 "# if USESHADOWMAPPCF > 1\n"
2472 " float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2473 " float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2474 " float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2475 " float4 group4 = step(shadowmaptc.z, texval(-2.0, 0.0));\n"
2476 " float4 group5 = step(shadowmaptc.z, texval( 0.0, 0.0));\n"
2477 " float4 group6 = step(shadowmaptc.z, texval( 2.0, 0.0));\n"
2478 " float4 group7 = step(shadowmaptc.z, texval(-2.0, 2.0));\n"
2479 " float4 group8 = step(shadowmaptc.z, texval( 0.0, 2.0));\n"
2480 " float4 group9 = step(shadowmaptc.z, texval( 2.0, 2.0));\n"
2481 " float4 locols = float4(group1.ab, group3.ab);\n"
2482 " float4 hicols = float4(group7.rg, group9.rg);\n"
2483 " locols.yz += group2.ab;\n"
2484 " hicols.yz += group8.rg;\n"
2485 " float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2486 " float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2487 " lerp(locols, hicols, offset.y);\n"
2488 " float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2489 " cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2490 " f = dot(cols, float4(1.0/25.0));\n"
2492 " float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2493 " float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2494 " float4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
2495 " float4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
2496 " float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2497 " lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2498 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2501 "# ifdef GL_EXT_gpu_shader4\n"
2502 "# define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2504 "# define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r \n"
2506 "# if USESHADOWMAPPCF > 1\n"
2507 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2508 " center *= ShadowMap_TextureScale;\n"
2509 " 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"
2510 " 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"
2511 " 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"
2512 " 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"
2513 " float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2514 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2516 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2517 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2518 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2519 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2520 " float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2521 " f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2525 " f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2528 "# ifdef USESHADOWMAPORTHO\n"
2529 " return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2535 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2536 "#endif // FRAGMENT_SHADER\n"
2541 "#ifdef MODE_DEFERREDGEOMETRY\n"
2542 "#ifdef VERTEX_SHADER\n"
2545 "float4 gl_Vertex : POSITION,\n"
2546 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2547 "#ifdef USEVERTEXTEXTUREBLEND\n"
2548 "float4 gl_Color : COLOR0,\n"
2550 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2551 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2552 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2553 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2554 "uniform float4x4 TexMatrix : register(c0),\n"
2555 "#ifdef USEVERTEXTEXTUREBLEND\n"
2556 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2558 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2559 "#ifdef USEOFFSETMAPPING\n"
2560 "uniform float3 EyePosition : register(c24),\n"
2562 "out float4 gl_Position : POSITION,\n"
2563 "#ifdef USEVERTEXTEXTUREBLEND\n"
2564 "out float4 gl_FrontColor : COLOR,\n"
2566 "out float4 TexCoordBoth : TEXCOORD0,\n"
2567 "#ifdef USEOFFSETMAPPING\n"
2568 "out float3 EyeVector : TEXCOORD2,\n"
2570 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2571 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2572 "out float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\n"
2575 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2576 "#ifdef USEVERTEXTEXTUREBLEND\n"
2578 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2580 " gl_FrontColor = gl_Color; // Cg is forward\n"
2582 " TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2585 " // transform unnormalized eye direction into tangent space\n"
2586 "#ifdef USEOFFSETMAPPING\n"
2587 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2588 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2589 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2590 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2593 " VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2594 " VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2595 " VectorR.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2596 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2597 " VectorR.w = gl_Position.z;\n"
2599 "#endif // VERTEX_SHADER\n"
2601 "#ifdef FRAGMENT_SHADER\n"
2604 "float4 TexCoordBoth : TEXCOORD0,\n"
2605 "float3 EyeVector : TEXCOORD2,\n"
2606 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2607 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2608 "float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
2609 "uniform sampler Texture_Normal : register(s0),\n"
2610 "#ifdef USEALPHAKILL\n"
2611 "uniform sampler Texture_Color : register(s1),\n"
2613 "uniform sampler Texture_Gloss : register(s2),\n"
2614 "#ifdef USEVERTEXTEXTUREBLEND\n"
2615 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2616 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2618 "#ifdef USEOFFSETMAPPING\n"
2619 "uniform float OffsetMapping_Scale : register(c24),\n"
2621 "uniform half SpecularPower : register(c36),\n"
2623 "out float4 gl_FragData0 : COLOR0,\n"
2624 "out float4 gl_FragData1 : COLOR1\n"
2626 "out float4 gl_FragColor : COLOR\n"
2630 " float2 TexCoord = TexCoordBoth.xy;\n"
2631 "#ifdef USEOFFSETMAPPING\n"
2632 " // apply offsetmapping\n"
2633 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2634 "#define TexCoord TexCoordOffset\n"
2637 "#ifdef USEALPHAKILL\n"
2638 " if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2642 "#ifdef USEVERTEXTEXTUREBLEND\n"
2643 " float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2644 " float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2645 " //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2646 " //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2649 "#ifdef USEVERTEXTEXTUREBLEND\n"
2650 " float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2651 " float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2653 " float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2654 " float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2658 " 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"
2659 " float Depth = VectorR.w / 256.0;\n"
2660 " float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
2661 "// float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
2662 " depthcolor.yz -= floor(depthcolor.yz);\n"
2663 " gl_FragData1 = depthcolor;\n"
2665 " gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2668 "#endif // FRAGMENT_SHADER\n"
2669 "#else // !MODE_DEFERREDGEOMETRY\n"
2674 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2675 "#ifdef VERTEX_SHADER\n"
2678 "float4 gl_Vertex : POSITION,\n"
2679 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2680 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2681 "out float4 gl_Position : POSITION,\n"
2682 "out float4 ModelViewPosition : TEXCOORD0\n"
2685 " ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2686 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2688 "#endif // VERTEX_SHADER\n"
2690 "#ifdef FRAGMENT_SHADER\n"
2694 "float2 Pixel : VPOS,\n"
2696 "float2 Pixel : WPOS,\n"
2698 "float4 ModelViewPosition : TEXCOORD0,\n"
2699 "uniform float4x4 ViewToLight : register(c44),\n"
2700 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2701 "uniform float3 LightPosition : register(c23),\n"
2702 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2703 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2704 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2705 "#ifdef USESPECULAR\n"
2706 "uniform half3 DeferredColor_Specular : register(c11),\n"
2707 "uniform half SpecularPower : register(c36),\n"
2709 "uniform sampler Texture_Attenuation : register(s9),\n"
2710 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2711 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2713 "#ifdef USECUBEFILTER\n"
2714 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2717 "#ifdef USESHADOWMAP2D\n"
2718 "# ifdef USESHADOWSAMPLER\n"
2719 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2721 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2725 "#ifdef USESHADOWMAPVSDCT\n"
2726 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2729 "#if defined(USESHADOWMAP2D)\n"
2730 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2731 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2734 "out float4 gl_FragData0 : COLOR0,\n"
2735 "out float4 gl_FragData1 : COLOR1\n"
2738 " // calculate viewspace pixel position\n"
2739 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2740 " //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2741 " float3 position;\n"
2743 " position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
2745 " position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2747 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2748 " // decode viewspace pixel normal\n"
2749 " half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2750 " half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2751 " // surfacenormal = pixel normal in viewspace\n"
2752 " // LightVector = pixel to light in viewspace\n"
2753 " // CubeVector = position in lightspace\n"
2754 " // eyevector = pixel to view in viewspace\n"
2755 " float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2756 " half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2757 "#ifdef USEDIFFUSE\n"
2758 " // calculate diffuse shading\n"
2759 " half3 lightnormal = half3(normalize(LightPosition - position));\n"
2760 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2762 "#ifdef USESPECULAR\n"
2763 " // calculate directional shading\n"
2764 " float3 eyevector = position * -1.0;\n"
2765 "# ifdef USEEXACTSPECULARMATH\n"
2766 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
2768 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2769 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
2773 "#if defined(USESHADOWMAP2D)\n"
2774 " fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2775 "#ifdef USESHADOWMAPVSDCT\n"
2776 ", Texture_CubeProjection\n"
2781 "#ifdef USEDIFFUSE\n"
2782 " gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2784 " gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2786 "#ifdef USESPECULAR\n"
2787 " gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2789 " gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2792 "# ifdef USECUBEFILTER\n"
2793 " float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2794 " gl_FragData0.rgb *= cubecolor;\n"
2795 " gl_FragData1.rgb *= cubecolor;\n"
2798 "#endif // FRAGMENT_SHADER\n"
2799 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2804 "#ifdef VERTEX_SHADER\n"
2807 "float4 gl_Vertex : POSITION,\n"
2808 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2809 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2810 "float4 gl_Color : COLOR0,\n"
2812 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2813 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2814 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2815 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2816 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2818 "uniform float3 EyePosition : register(c24),\n"
2819 "uniform float4x4 TexMatrix : register(c0),\n"
2820 "#ifdef USEVERTEXTEXTUREBLEND\n"
2821 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2823 "#ifdef MODE_LIGHTSOURCE\n"
2824 "uniform float4x4 ModelToLight : register(c20),\n"
2826 "#ifdef MODE_LIGHTSOURCE\n"
2827 "uniform float3 LightPosition : register(c27),\n"
2829 "#ifdef MODE_LIGHTDIRECTION\n"
2830 "uniform float3 LightDir : register(c26),\n"
2832 "uniform float4 FogPlane : register(c25),\n"
2833 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2834 "uniform float3 LightPosition : register(c27),\n"
2836 "#ifdef USESHADOWMAPORTHO\n"
2837 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2839 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2840 "out float4 gl_FrontColor : COLOR,\n"
2842 "out float4 TexCoordBoth : TEXCOORD0,\n"
2843 "#ifdef USELIGHTMAP\n"
2844 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2846 "#ifdef USEEYEVECTOR\n"
2847 "out float3 EyeVector : TEXCOORD2,\n"
2849 "#ifdef USEREFLECTION\n"
2850 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2853 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2855 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE) || defined(USEDIFFUSE)\n"
2856 "out float3 LightVector : TEXCOORD1,\n"
2858 "#ifdef MODE_LIGHTSOURCE\n"
2859 "out float3 CubeVector : TEXCOORD3,\n"
2861 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2862 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2863 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2864 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2866 "#ifdef USESHADOWMAPORTHO\n"
2867 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2869 "out float4 gl_Position : POSITION\n"
2872 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2874 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2876 " gl_FrontColor = gl_Color; // Cg is forward\n"
2879 " // copy the surface texcoord\n"
2880 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2881 "#ifdef USEVERTEXTEXTUREBLEND\n"
2882 " TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2884 "#ifdef USELIGHTMAP\n"
2885 " TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2888 "#ifdef MODE_LIGHTSOURCE\n"
2889 " // transform vertex position into light attenuation/cubemap space\n"
2890 " // (-1 to +1 across the light box)\n"
2891 " CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2893 "# ifdef USEDIFFUSE\n"
2894 " // transform unnormalized light direction into tangent space\n"
2895 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
2896 " // normalize it per pixel)\n"
2897 " float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2898 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2899 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2900 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2904 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2905 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2906 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2907 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2910 " // transform unnormalized eye direction into tangent space\n"
2911 "#ifdef USEEYEVECTOR\n"
2912 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2913 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2914 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2915 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2919 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2920 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2923 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2924 " VectorS = gl_MultiTexCoord1.xyz;\n"
2925 " VectorT = gl_MultiTexCoord2.xyz;\n"
2926 " VectorR = gl_MultiTexCoord3.xyz;\n"
2929 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2930 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2932 "#ifdef USESHADOWMAPORTHO\n"
2933 " ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2936 "#ifdef USEREFLECTION\n"
2937 " ModelViewProjectionPosition = gl_Position;\n"
2940 "#endif // VERTEX_SHADER\n"
2945 "#ifdef FRAGMENT_SHADER\n"
2948 "#ifdef USEDEFERREDLIGHTMAP\n"
2950 "float2 Pixel : VPOS,\n"
2952 "float2 Pixel : WPOS,\n"
2955 "float4 gl_FrontColor : COLOR,\n"
2956 "float4 TexCoordBoth : TEXCOORD0,\n"
2957 "#ifdef USELIGHTMAP\n"
2958 "float2 TexCoordLightmap : TEXCOORD1,\n"
2960 "#ifdef USEEYEVECTOR\n"
2961 "float3 EyeVector : TEXCOORD2,\n"
2963 "#ifdef USEREFLECTION\n"
2964 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2967 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2969 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2970 "float3 LightVector : TEXCOORD1,\n"
2972 "#ifdef MODE_LIGHTSOURCE\n"
2973 "float3 CubeVector : TEXCOORD3,\n"
2975 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2976 "float4 ModelViewPosition : TEXCOORD0,\n"
2978 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2979 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2980 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2981 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2983 "#ifdef USESHADOWMAPORTHO\n"
2984 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2987 "uniform sampler Texture_Normal : register(s0),\n"
2988 "uniform sampler Texture_Color : register(s1),\n"
2989 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2990 "uniform sampler Texture_Gloss : register(s2),\n"
2993 "uniform sampler Texture_Glow : register(s3),\n"
2995 "#ifdef USEVERTEXTEXTUREBLEND\n"
2996 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2997 "uniform sampler Texture_SecondaryColor : register(s5),\n"
2998 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2999 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
3002 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
3005 "#ifdef USECOLORMAPPING\n"
3006 "uniform sampler Texture_Pants : register(s4),\n"
3007 "uniform sampler Texture_Shirt : register(s7),\n"
3010 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
3011 "uniform sampler Texture_FogMask : register(s8),\n"
3013 "#ifdef USELIGHTMAP\n"
3014 "uniform sampler Texture_Lightmap : register(s9),\n"
3016 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
3017 "uniform sampler Texture_Deluxemap : register(s10),\n"
3019 "#ifdef USEREFLECTION\n"
3020 "uniform sampler Texture_Reflection : register(s7),\n"
3023 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
3024 "uniform sampler Texture_ScreenDepth : register(s13),\n"
3025 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
3027 "#ifdef USEDEFERREDLIGHTMAP\n"
3028 "uniform sampler Texture_ScreenDepth : register(s13),\n"
3029 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
3030 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
3031 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
3034 "#ifdef USECOLORMAPPING\n"
3035 "uniform half3 Color_Pants : register(c7),\n"
3036 "uniform half3 Color_Shirt : register(c8),\n"
3039 "uniform float3 FogColor : register(c16),\n"
3040 "uniform float FogRangeRecip : register(c20),\n"
3041 "uniform float FogPlaneViewDist : register(c19),\n"
3042 "uniform float FogHeightFade : register(c17),\n"
3045 "#ifdef USEOFFSETMAPPING\n"
3046 "uniform float OffsetMapping_Scale : register(c24),\n"
3049 "#ifdef USEDEFERREDLIGHTMAP\n"
3050 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
3051 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
3052 "uniform half3 DeferredMod_Specular : register(c13),\n"
3054 "uniform half3 Color_Ambient : register(c3),\n"
3055 "uniform half3 Color_Diffuse : register(c4),\n"
3056 "uniform half3 Color_Specular : register(c5),\n"
3057 "uniform half SpecularPower : register(c36),\n"
3059 "uniform half3 Color_Glow : register(c6),\n"
3061 "uniform half Alpha : register(c0),\n"
3062 "#ifdef USEREFLECTION\n"
3063 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3064 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3065 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3066 "uniform half4 ReflectColor : register(c26),\n"
3068 "#ifdef USEREFLECTCUBE\n"
3069 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3070 "uniform sampler Texture_ReflectMask : register(s5),\n"
3071 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3073 "#ifdef MODE_LIGHTDIRECTION\n"
3074 "uniform half3 LightColor : register(c21),\n"
3076 "#ifdef MODE_LIGHTSOURCE\n"
3077 "uniform half3 LightColor : register(c21),\n"
3080 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3081 "uniform sampler Texture_Attenuation : register(s9),\n"
3082 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3085 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3087 "#ifdef USESHADOWMAP2D\n"
3088 "# ifdef USESHADOWSAMPLER\n"
3089 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3091 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3095 "#ifdef USESHADOWMAPVSDCT\n"
3096 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3099 "#if defined(USESHADOWMAP2D)\n"
3100 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3101 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3103 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3105 "out float4 gl_FragColor : COLOR\n"
3108 " float2 TexCoord = TexCoordBoth.xy;\n"
3109 "#ifdef USEVERTEXTEXTUREBLEND\n"
3110 " float2 TexCoord2 = TexCoordBoth.zw;\n"
3112 "#ifdef USEOFFSETMAPPING\n"
3113 " // apply offsetmapping\n"
3114 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3115 "#define TexCoord TexCoordOffset\n"
3118 " // combine the diffuse textures (base, pants, shirt)\n"
3119 " half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3120 "#ifdef USEALPHAKILL\n"
3121 " if (color.a < 0.5)\n"
3124 " color.a *= Alpha;\n"
3125 "#ifdef USECOLORMAPPING\n"
3126 " color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3128 "#ifdef USEVERTEXTEXTUREBLEND\n"
3129 " half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3130 " //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3131 " //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3132 " color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3134 " //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3137 " // get the surface normal\n"
3138 "#ifdef USEVERTEXTEXTUREBLEND\n"
3139 " half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3141 " half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3144 " // get the material colors\n"
3145 " half3 diffusetex = color.rgb;\n"
3146 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3147 "# ifdef USEVERTEXTEXTUREBLEND\n"
3148 " half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3150 " half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3154 "#ifdef USEREFLECTCUBE\n"
3155 " float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3156 " float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3157 " float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3158 " diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3164 "#ifdef MODE_LIGHTSOURCE\n"
3165 " // light source\n"
3166 "#ifdef USEDIFFUSE\n"
3167 " half3 lightnormal = half3(normalize(LightVector));\n"
3168 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3169 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3170 "#ifdef USESPECULAR\n"
3171 "#ifdef USEEXACTSPECULARMATH\n"
3172 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3174 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3175 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3177 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3180 " color.rgb = diffusetex * Color_Ambient;\n"
3182 " color.rgb *= LightColor;\n"
3183 " color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3184 "#if defined(USESHADOWMAP2D)\n"
3185 " color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3186 "#ifdef USESHADOWMAPVSDCT\n"
3187 ", Texture_CubeProjection\n"
3192 "# ifdef USECUBEFILTER\n"
3193 " color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3196 "#ifdef USESHADOWMAP2D\n"
3197 "#ifdef USESHADOWMAPVSDCT\n"
3198 "// float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3200 "// float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3202 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3203 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3204 "// color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3205 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3206 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3207 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3208 "// color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3209 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3210 "// color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3211 "// color.r = half(shadowmaptc.z);\n"
3212 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3213 "// color.r = half(shadowmaptc.z);\n"
3215 "// color.rgb = abs(CubeVector);\n"
3217 "// color.rgb = half3(1,1,1);\n"
3218 "#endif // MODE_LIGHTSOURCE\n"
3223 "#ifdef MODE_LIGHTDIRECTION\n"
3225 "#ifdef USEDIFFUSE\n"
3226 " half3 lightnormal = half3(normalize(LightVector));\n"
3228 "#define lightcolor LightColor\n"
3229 "#endif // MODE_LIGHTDIRECTION\n"
3230 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3232 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3233 " half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3234 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3235 " // convert modelspace light vector to tangentspace\n"
3236 " half3 lightnormal;\n"
3237 " lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3238 " lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3239 " lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3240 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3241 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3242 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3243 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3244 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3245 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3246 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3247 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3248 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3249 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3250 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3251 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3253 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3254 " half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3255 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3261 "#ifdef MODE_FAKELIGHT\n"
3263 "half3 lightnormal = half3(normalize(EyeVector));\n"
3264 "half3 lightcolor = half3(1.0,1.0,1.0);\n"
3265 "#endif // MODE_FAKELIGHT\n"
3270 "#ifdef MODE_LIGHTMAP\n"
3271 " color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3272 "#endif // MODE_LIGHTMAP\n"
3273 "#ifdef MODE_VERTEXCOLOR\n"
3274 " color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3275 "#endif // MODE_VERTEXCOLOR\n"
3276 "#ifdef MODE_FLATCOLOR\n"
3277 " color.rgb = diffusetex * Color_Ambient;\n"
3278 "#endif // MODE_FLATCOLOR\n"
3284 "# ifdef USEDIFFUSE\n"
3285 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3286 "# ifdef USESPECULAR\n"
3287 "# ifdef USEEXACTSPECULARMATH\n"
3288 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3290 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3291 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3293 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3295 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3298 " color.rgb = diffusetex * Color_Ambient;\n"
3302 "#ifdef USESHADOWMAPORTHO\n"
3303 " color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
3306 "#ifdef USEDEFERREDLIGHTMAP\n"
3307 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3308 " color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3309 " color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3310 "// color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
3311 "// color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
3315 "#ifdef USEVERTEXTEXTUREBLEND\n"
3316 " color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3318 " color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3323 " color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3326 " // 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"
3327 "#ifdef USEREFLECTION\n"
3328 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3329 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3330 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3331 " float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3332 " // FIXME temporary hack to detect the case that the reflection\n"
3333 " // gets blackened at edges due to leaving the area that contains actual\n"
3335 " // Remove this 'ack once we have a better way to stop this thing from\n"
3337 " float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3338 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3339 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3340 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3341 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3342 " color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3345 " gl_FragColor = float4(color);\n"
3347 "#endif // FRAGMENT_SHADER\n"
3349 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3350 "#endif // !MODE_DEFERREDGEOMETRY\n"
3351 "#endif // !MODE_WATER\n"
3352 "#endif // !MODE_REFRACTION\n"
3353 "#endif // !MODE_BLOOMBLUR\n"
3354 "#endif // !MODE_GENERIC\n"
3355 "#endif // !MODE_POSTPROCESS\n"
3356 "#endif // !MODE_SHOWDEPTH\n"
3357 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3360 char *glslshaderstring = NULL;
3361 char *hlslshaderstring = NULL;
3363 //=======================================================================================================================================================
3365 typedef struct shaderpermutationinfo_s
3367 const char *pretext;
3370 shaderpermutationinfo_t;
3372 typedef struct shadermodeinfo_s
3374 const char *vertexfilename;
3375 const char *geometryfilename;
3376 const char *fragmentfilename;
3377 const char *pretext;
3382 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3383 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3385 {"#define USEDIFFUSE\n", " diffuse"},
3386 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3387 {"#define USEVIEWTINT\n", " viewtint"},
3388 {"#define USECOLORMAPPING\n", " colormapping"},
3389 {"#define USESATURATION\n", " saturation"},
3390 {"#define USEFOGINSIDE\n", " foginside"},
3391 {"#define USEFOGOUTSIDE\n", " fogoutside"},
3392 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3393 {"#define USEGAMMARAMPS\n", " gammaramps"},
3394 {"#define USECUBEFILTER\n", " cubefilter"},
3395 {"#define USEGLOW\n", " glow"},
3396 {"#define USEBLOOM\n", " bloom"},
3397 {"#define USESPECULAR\n", " specular"},
3398 {"#define USEPOSTPROCESSING\n", " postprocessing"},
3399 {"#define USEREFLECTION\n", " reflection"},
3400 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3401 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3402 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3403 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3404 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3405 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3406 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3407 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3408 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3409 {"#define USEALPHAKILL\n", " alphakill"},
3410 {"#define USEREFLECTCUBE\n", " reflectcube"},
3411 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
3412 {"#define USEBOUNCEGRID\n", " bouncegrid"},
3415 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3416 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3418 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3419 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3420 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3421 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3422 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3423 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3424 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3425 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3426 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3427 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3428 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3429 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3430 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3431 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3432 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3433 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3436 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3438 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3439 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3440 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3441 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3442 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3443 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3444 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3445 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3446 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3447 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3448 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3449 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3450 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3451 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3452 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3453 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3456 struct r_glsl_permutation_s;
3457 typedef struct r_glsl_permutation_s
3459 /// hash lookup data
3460 struct r_glsl_permutation_s *hashnext;
3462 unsigned int permutation;
3464 /// indicates if we have tried compiling this permutation already
3466 /// 0 if compilation failed
3468 // texture units assigned to each detected uniform
3469 int tex_Texture_First;
3470 int tex_Texture_Second;
3471 int tex_Texture_GammaRamps;
3472 int tex_Texture_Normal;
3473 int tex_Texture_Color;
3474 int tex_Texture_Gloss;
3475 int tex_Texture_Glow;
3476 int tex_Texture_SecondaryNormal;
3477 int tex_Texture_SecondaryColor;
3478 int tex_Texture_SecondaryGloss;
3479 int tex_Texture_SecondaryGlow;
3480 int tex_Texture_Pants;
3481 int tex_Texture_Shirt;
3482 int tex_Texture_FogHeightTexture;
3483 int tex_Texture_FogMask;
3484 int tex_Texture_Lightmap;
3485 int tex_Texture_Deluxemap;
3486 int tex_Texture_Attenuation;
3487 int tex_Texture_Cube;
3488 int tex_Texture_Refraction;
3489 int tex_Texture_Reflection;
3490 int tex_Texture_ShadowMap2D;
3491 int tex_Texture_CubeProjection;
3492 int tex_Texture_ScreenDepth;
3493 int tex_Texture_ScreenNormalMap;
3494 int tex_Texture_ScreenDiffuse;
3495 int tex_Texture_ScreenSpecular;
3496 int tex_Texture_ReflectMask;
3497 int tex_Texture_ReflectCube;
3498 int tex_Texture_BounceGrid;
3499 /// locations of detected uniforms in program object, or -1 if not found
3500 int loc_Texture_First;
3501 int loc_Texture_Second;
3502 int loc_Texture_GammaRamps;
3503 int loc_Texture_Normal;
3504 int loc_Texture_Color;
3505 int loc_Texture_Gloss;
3506 int loc_Texture_Glow;
3507 int loc_Texture_SecondaryNormal;
3508 int loc_Texture_SecondaryColor;
3509 int loc_Texture_SecondaryGloss;
3510 int loc_Texture_SecondaryGlow;
3511 int loc_Texture_Pants;
3512 int loc_Texture_Shirt;
3513 int loc_Texture_FogHeightTexture;
3514 int loc_Texture_FogMask;
3515 int loc_Texture_Lightmap;
3516 int loc_Texture_Deluxemap;
3517 int loc_Texture_Attenuation;
3518 int loc_Texture_Cube;
3519 int loc_Texture_Refraction;
3520 int loc_Texture_Reflection;
3521 int loc_Texture_ShadowMap2D;
3522 int loc_Texture_CubeProjection;
3523 int loc_Texture_ScreenDepth;
3524 int loc_Texture_ScreenNormalMap;
3525 int loc_Texture_ScreenDiffuse;
3526 int loc_Texture_ScreenSpecular;
3527 int loc_Texture_ReflectMask;
3528 int loc_Texture_ReflectCube;
3529 int loc_Texture_BounceGrid;
3531 int loc_BloomBlur_Parameters;
3533 int loc_Color_Ambient;
3534 int loc_Color_Diffuse;
3535 int loc_Color_Specular;
3537 int loc_Color_Pants;
3538 int loc_Color_Shirt;
3539 int loc_DeferredColor_Ambient;
3540 int loc_DeferredColor_Diffuse;
3541 int loc_DeferredColor_Specular;
3542 int loc_DeferredMod_Diffuse;
3543 int loc_DeferredMod_Specular;
3544 int loc_DistortScaleRefractReflect;
3545 int loc_EyePosition;
3547 int loc_FogHeightFade;
3549 int loc_FogPlaneViewDist;
3550 int loc_FogRangeRecip;
3553 int loc_LightPosition;
3554 int loc_OffsetMapping_Scale;
3556 int loc_ReflectColor;
3557 int loc_ReflectFactor;
3558 int loc_ReflectOffset;
3559 int loc_RefractColor;
3561 int loc_ScreenCenterRefractReflect;
3562 int loc_ScreenScaleRefractReflect;
3563 int loc_ScreenToDepth;
3564 int loc_ShadowMap_Parameters;
3565 int loc_ShadowMap_TextureScale;
3566 int loc_SpecularPower;
3571 int loc_ViewTintColor;
3572 int loc_ViewToLight;
3573 int loc_ModelToLight;
3575 int loc_BackgroundTexMatrix;
3576 int loc_ModelViewProjectionMatrix;
3577 int loc_ModelViewMatrix;
3578 int loc_PixelToScreenTexCoord;
3579 int loc_ModelToReflectCube;
3580 int loc_ShadowMapMatrix;
3581 int loc_BloomColorSubtract;
3582 int loc_NormalmapScrollBlend;
3583 int loc_BounceGridMatrix;
3584 int loc_BounceGridIntensity;
3586 r_glsl_permutation_t;
3588 #define SHADERPERMUTATION_HASHSIZE 256
3591 // non-degradable "lightweight" shader parameters to keep the permutations simpler
3592 // these can NOT degrade! only use for simple stuff
3595 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
3596 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3597 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
3598 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
3599 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
3600 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5 ///< postprocess uservec4 is enabled
3602 #define SHADERSTATICPARMS_COUNT 6
3604 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
3605 static int shaderstaticparms_count = 0;
3607 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
3608 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
3609 qboolean R_CompileShader_CheckStaticParms(void)
3611 static int r_compileshader_staticparms_save[1];
3612 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
3613 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
3616 if (r_glsl_saturation_redcompensate.integer)
3617 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
3618 if (r_shadow_glossexact.integer)
3619 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
3620 if (r_glsl_postprocess.integer)
3622 if (r_glsl_postprocess_uservec1_enable.integer)
3623 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
3624 if (r_glsl_postprocess_uservec2_enable.integer)
3625 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
3626 if (r_glsl_postprocess_uservec3_enable.integer)
3627 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
3628 if (r_glsl_postprocess_uservec4_enable.integer)
3629 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
3631 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
3634 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
3635 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
3636 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
3638 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
3639 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
3641 shaderstaticparms_count = 0;
3644 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
3645 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
3646 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
3647 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
3648 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
3649 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
3652 /// information about each possible shader permutation
3653 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3654 /// currently selected permutation
3655 r_glsl_permutation_t *r_glsl_permutation;
3656 /// storage for permutations linked in the hash table
3657 memexpandablearray_t r_glsl_permutationarray;
3659 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3661 //unsigned int hashdepth = 0;
3662 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3663 r_glsl_permutation_t *p;
3664 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3666 if (p->mode == mode && p->permutation == permutation)
3668 //if (hashdepth > 10)
3669 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3674 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3676 p->permutation = permutation;
3677 p->hashnext = r_glsl_permutationhash[mode][hashindex];
3678 r_glsl_permutationhash[mode][hashindex] = p;
3679 //if (hashdepth > 10)
3680 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3684 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3687 if (!filename || !filename[0])
3689 if (!strcmp(filename, "glsl/default.glsl"))
3691 if (!glslshaderstring)
3693 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3694 if (glslshaderstring)
3695 Con_DPrintf("Loading shaders from file %s...\n", filename);
3697 glslshaderstring = (char *)builtinshaderstring;
3699 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3700 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3701 return shaderstring;
3703 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3706 if (printfromdisknotice)
3707 Con_DPrintf("from disk %s... ", filename);
3708 return shaderstring;
3710 return shaderstring;
3713 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3717 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3718 char *vertexstring, *geometrystring, *fragmentstring;
3719 char permutationname[256];
3720 int vertstrings_count = 0;
3721 int geomstrings_count = 0;
3722 int fragstrings_count = 0;
3723 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3724 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3725 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3732 permutationname[0] = 0;
3733 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
3734 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3735 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3737 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3739 // the first pretext is which type of shader to compile as
3740 // (later these will all be bound together as a program object)
3741 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3742 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3743 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3745 // the second pretext is the mode (for example a light source)
3746 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3747 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3748 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3749 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3751 // now add all the permutation pretexts
3752 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3754 if (permutation & (1<<i))
3756 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3757 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3758 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3759 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3763 // keep line numbers correct
3764 vertstrings_list[vertstrings_count++] = "\n";
3765 geomstrings_list[geomstrings_count++] = "\n";
3766 fragstrings_list[fragstrings_count++] = "\n";
3771 R_CompileShader_AddStaticParms(mode, permutation);
3772 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3773 vertstrings_count += shaderstaticparms_count;
3774 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3775 geomstrings_count += shaderstaticparms_count;
3776 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3777 fragstrings_count += shaderstaticparms_count;
3779 // now append the shader text itself
3780 vertstrings_list[vertstrings_count++] = vertexstring;
3781 geomstrings_list[geomstrings_count++] = geometrystring;
3782 fragstrings_list[fragstrings_count++] = fragmentstring;
3784 // if any sources were NULL, clear the respective list
3786 vertstrings_count = 0;
3787 if (!geometrystring)
3788 geomstrings_count = 0;
3789 if (!fragmentstring)
3790 fragstrings_count = 0;
3792 // compile the shader program
3793 if (vertstrings_count + geomstrings_count + fragstrings_count)
3794 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3798 qglUseProgram(p->program);CHECKGLERROR
3799 // look up all the uniform variable names we care about, so we don't
3800 // have to look them up every time we set them
3802 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
3803 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
3804 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
3805 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
3806 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
3807 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
3808 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
3809 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
3810 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
3811 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
3812 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
3813 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
3814 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
3815 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
3816 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
3817 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
3818 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
3819 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
3820 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
3821 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
3822 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
3823 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
3824 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
3825 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
3826 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
3827 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
3828 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
3829 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
3830 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
3831 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
3832 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
3833 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
3834 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
3835 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
3836 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
3837 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
3838 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
3839 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
3840 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
3841 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
3842 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
3843 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
3844 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
3845 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
3846 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
3847 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
3848 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
3849 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
3850 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
3851 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
3852 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
3853 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
3854 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
3855 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
3856 p->loc_OffsetMapping_Scale = qglGetUniformLocation(p->program, "OffsetMapping_Scale");
3857 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
3858 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
3859 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
3860 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
3861 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
3862 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
3863 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
3864 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
3865 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
3866 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
3867 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
3868 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
3869 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
3870 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
3871 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
3872 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
3873 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
3874 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
3875 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
3876 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
3877 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
3878 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
3879 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
3880 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
3881 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
3882 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
3883 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
3884 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
3885 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
3886 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
3887 // initialize the samplers to refer to the texture units we use
3888 p->tex_Texture_First = -1;
3889 p->tex_Texture_Second = -1;
3890 p->tex_Texture_GammaRamps = -1;
3891 p->tex_Texture_Normal = -1;
3892 p->tex_Texture_Color = -1;
3893 p->tex_Texture_Gloss = -1;
3894 p->tex_Texture_Glow = -1;
3895 p->tex_Texture_SecondaryNormal = -1;
3896 p->tex_Texture_SecondaryColor = -1;
3897 p->tex_Texture_SecondaryGloss = -1;
3898 p->tex_Texture_SecondaryGlow = -1;
3899 p->tex_Texture_Pants = -1;
3900 p->tex_Texture_Shirt = -1;
3901 p->tex_Texture_FogHeightTexture = -1;
3902 p->tex_Texture_FogMask = -1;
3903 p->tex_Texture_Lightmap = -1;
3904 p->tex_Texture_Deluxemap = -1;
3905 p->tex_Texture_Attenuation = -1;
3906 p->tex_Texture_Cube = -1;
3907 p->tex_Texture_Refraction = -1;
3908 p->tex_Texture_Reflection = -1;
3909 p->tex_Texture_ShadowMap2D = -1;
3910 p->tex_Texture_CubeProjection = -1;
3911 p->tex_Texture_ScreenDepth = -1;
3912 p->tex_Texture_ScreenNormalMap = -1;
3913 p->tex_Texture_ScreenDiffuse = -1;
3914 p->tex_Texture_ScreenSpecular = -1;
3915 p->tex_Texture_ReflectMask = -1;
3916 p->tex_Texture_ReflectCube = -1;
3917 p->tex_Texture_BounceGrid = -1;
3919 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
3920 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
3921 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
3922 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
3923 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
3924 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
3925 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
3926 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
3927 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
3928 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
3929 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
3930 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
3931 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
3932 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
3933 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
3934 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
3935 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
3936 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
3937 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
3938 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
3939 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
3940 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
3941 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
3942 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
3943 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
3944 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
3945 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
3946 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
3947 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
3948 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
3950 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
3953 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
3957 Mem_Free(vertexstring);
3959 Mem_Free(geometrystring);
3961 Mem_Free(fragmentstring);
3964 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3966 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3967 if (r_glsl_permutation != perm)
3969 r_glsl_permutation = perm;
3970 if (!r_glsl_permutation->program)
3972 if (!r_glsl_permutation->compiled)
3973 R_GLSL_CompilePermutation(perm, mode, permutation);
3974 if (!r_glsl_permutation->program)
3976 // remove features until we find a valid permutation
3978 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3980 // reduce i more quickly whenever it would not remove any bits
3981 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3982 if (!(permutation & j))
3985 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3986 if (!r_glsl_permutation->compiled)
3987 R_GLSL_CompilePermutation(perm, mode, permutation);
3988 if (r_glsl_permutation->program)
3991 if (i >= SHADERPERMUTATION_COUNT)
3993 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3994 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3995 qglUseProgram(0);CHECKGLERROR
3996 return; // no bit left to clear, entire mode is broken
4001 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
4003 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
4004 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
4005 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
4012 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4013 extern D3DCAPS9 vid_d3d9caps;
4016 struct r_hlsl_permutation_s;
4017 typedef struct r_hlsl_permutation_s
4019 /// hash lookup data
4020 struct r_hlsl_permutation_s *hashnext;
4022 unsigned int permutation;
4024 /// indicates if we have tried compiling this permutation already
4026 /// NULL if compilation failed
4027 IDirect3DVertexShader9 *vertexshader;
4028 IDirect3DPixelShader9 *pixelshader;
4030 r_hlsl_permutation_t;
4032 typedef enum D3DVSREGISTER_e
4034 D3DVSREGISTER_TexMatrix = 0, // float4x4
4035 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4036 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4037 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4038 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4039 D3DVSREGISTER_ModelToLight = 20, // float4x4
4040 D3DVSREGISTER_EyePosition = 24,
4041 D3DVSREGISTER_FogPlane = 25,
4042 D3DVSREGISTER_LightDir = 26,
4043 D3DVSREGISTER_LightPosition = 27,
4047 typedef enum D3DPSREGISTER_e
4049 D3DPSREGISTER_Alpha = 0,
4050 D3DPSREGISTER_BloomBlur_Parameters = 1,
4051 D3DPSREGISTER_ClientTime = 2,
4052 D3DPSREGISTER_Color_Ambient = 3,
4053 D3DPSREGISTER_Color_Diffuse = 4,
4054 D3DPSREGISTER_Color_Specular = 5,
4055 D3DPSREGISTER_Color_Glow = 6,
4056 D3DPSREGISTER_Color_Pants = 7,
4057 D3DPSREGISTER_Color_Shirt = 8,
4058 D3DPSREGISTER_DeferredColor_Ambient = 9,
4059 D3DPSREGISTER_DeferredColor_Diffuse = 10,
4060 D3DPSREGISTER_DeferredColor_Specular = 11,
4061 D3DPSREGISTER_DeferredMod_Diffuse = 12,
4062 D3DPSREGISTER_DeferredMod_Specular = 13,
4063 D3DPSREGISTER_DistortScaleRefractReflect = 14,
4064 D3DPSREGISTER_EyePosition = 15, // unused
4065 D3DPSREGISTER_FogColor = 16,
4066 D3DPSREGISTER_FogHeightFade = 17,
4067 D3DPSREGISTER_FogPlane = 18,
4068 D3DPSREGISTER_FogPlaneViewDist = 19,
4069 D3DPSREGISTER_FogRangeRecip = 20,
4070 D3DPSREGISTER_LightColor = 21,
4071 D3DPSREGISTER_LightDir = 22, // unused
4072 D3DPSREGISTER_LightPosition = 23,
4073 D3DPSREGISTER_OffsetMapping_Scale = 24,
4074 D3DPSREGISTER_PixelSize = 25,
4075 D3DPSREGISTER_ReflectColor = 26,
4076 D3DPSREGISTER_ReflectFactor = 27,
4077 D3DPSREGISTER_ReflectOffset = 28,
4078 D3DPSREGISTER_RefractColor = 29,
4079 D3DPSREGISTER_Saturation = 30,
4080 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4081 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4082 D3DPSREGISTER_ScreenToDepth = 33,
4083 D3DPSREGISTER_ShadowMap_Parameters = 34,
4084 D3DPSREGISTER_ShadowMap_TextureScale = 35,
4085 D3DPSREGISTER_SpecularPower = 36,
4086 D3DPSREGISTER_UserVec1 = 37,
4087 D3DPSREGISTER_UserVec2 = 38,
4088 D3DPSREGISTER_UserVec3 = 39,
4089 D3DPSREGISTER_UserVec4 = 40,
4090 D3DPSREGISTER_ViewTintColor = 41,
4091 D3DPSREGISTER_PixelToScreenTexCoord = 42,
4092 D3DPSREGISTER_BloomColorSubtract = 43,
4093 D3DPSREGISTER_ViewToLight = 44, // float4x4
4094 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4095 D3DPSREGISTER_NormalmapScrollBlend = 52,
4100 /// information about each possible shader permutation
4101 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4102 /// currently selected permutation
4103 r_hlsl_permutation_t *r_hlsl_permutation;
4104 /// storage for permutations linked in the hash table
4105 memexpandablearray_t r_hlsl_permutationarray;
4107 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4109 //unsigned int hashdepth = 0;
4110 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4111 r_hlsl_permutation_t *p;
4112 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4114 if (p->mode == mode && p->permutation == permutation)
4116 //if (hashdepth > 10)
4117 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4122 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4124 p->permutation = permutation;
4125 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4126 r_hlsl_permutationhash[mode][hashindex] = p;
4127 //if (hashdepth > 10)
4128 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4132 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4135 if (!filename || !filename[0])
4137 if (!strcmp(filename, "hlsl/default.hlsl"))
4139 if (!hlslshaderstring)
4141 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4142 if (hlslshaderstring)
4143 Con_DPrintf("Loading shaders from file %s...\n", filename);
4145 hlslshaderstring = (char *)builtinhlslshaderstring;
4147 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4148 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4149 return shaderstring;
4151 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4154 if (printfromdisknotice)
4155 Con_DPrintf("from disk %s... ", filename);
4156 return shaderstring;
4158 return shaderstring;
4162 //#include <d3dx9shader.h>
4163 //#include <d3dx9mesh.h>
4165 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4167 DWORD *vsbin = NULL;
4168 DWORD *psbin = NULL;
4169 fs_offset_t vsbinsize;
4170 fs_offset_t psbinsize;
4171 // IDirect3DVertexShader9 *vs = NULL;
4172 // IDirect3DPixelShader9 *ps = NULL;
4173 ID3DXBuffer *vslog = NULL;
4174 ID3DXBuffer *vsbuffer = NULL;
4175 ID3DXConstantTable *vsconstanttable = NULL;
4176 ID3DXBuffer *pslog = NULL;
4177 ID3DXBuffer *psbuffer = NULL;
4178 ID3DXConstantTable *psconstanttable = NULL;
4181 char temp[MAX_INPUTLINE];
4182 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4183 qboolean debugshader = gl_paranoid.integer != 0;
4184 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4185 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4188 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4189 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4191 if ((!vsbin && vertstring) || (!psbin && fragstring))
4193 const char* dllnames_d3dx9 [] =
4217 dllhandle_t d3dx9_dll = NULL;
4218 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4219 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4220 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4221 dllfunction_t d3dx9_dllfuncs[] =
4223 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
4224 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
4225 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
4228 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4230 DWORD shaderflags = 0;
4232 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4233 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4234 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4235 if (vertstring && vertstring[0])
4239 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4240 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4241 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4242 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4245 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4248 vsbinsize = vsbuffer->GetBufferSize();
4249 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4250 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4251 vsbuffer->Release();
4255 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4256 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4260 if (fragstring && fragstring[0])
4264 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4265 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4266 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4267 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4270 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4273 psbinsize = psbuffer->GetBufferSize();
4274 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4275 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4276 psbuffer->Release();
4280 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4281 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4285 Sys_UnloadLibrary(&d3dx9_dll);
4288 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4292 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4293 if (FAILED(vsresult))
4294 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4295 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4296 if (FAILED(psresult))
4297 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4299 // free the shader data
4300 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4301 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4304 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4307 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4308 int vertstring_length = 0;
4309 int geomstring_length = 0;
4310 int fragstring_length = 0;
4312 char *vertexstring, *geometrystring, *fragmentstring;
4313 char *vertstring, *geomstring, *fragstring;
4314 char permutationname[256];
4315 char cachename[256];
4316 int vertstrings_count = 0;
4317 int geomstrings_count = 0;
4318 int fragstrings_count = 0;
4319 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4320 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4321 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4326 p->vertexshader = NULL;
4327 p->pixelshader = NULL;
4329 permutationname[0] = 0;
4331 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
4332 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4333 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4335 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4336 strlcat(cachename, "hlsl/", sizeof(cachename));
4338 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4339 vertstrings_count = 0;
4340 geomstrings_count = 0;
4341 fragstrings_count = 0;
4342 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4343 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4344 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4346 // the first pretext is which type of shader to compile as
4347 // (later these will all be bound together as a program object)
4348 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4349 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4350 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4352 // the second pretext is the mode (for example a light source)
4353 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4354 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4355 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4356 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4357 strlcat(cachename, modeinfo->name, sizeof(cachename));
4359 // now add all the permutation pretexts
4360 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4362 if (permutation & (1<<i))
4364 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4365 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4366 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4367 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4368 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4372 // keep line numbers correct
4373 vertstrings_list[vertstrings_count++] = "\n";
4374 geomstrings_list[geomstrings_count++] = "\n";
4375 fragstrings_list[fragstrings_count++] = "\n";
4380 R_CompileShader_AddStaticParms(mode, permutation);
4381 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4382 vertstrings_count += shaderstaticparms_count;
4383 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4384 geomstrings_count += shaderstaticparms_count;
4385 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4386 fragstrings_count += shaderstaticparms_count;
4388 // replace spaces in the cachename with _ characters
4389 for (i = 0;cachename[i];i++)
4390 if (cachename[i] == ' ')
4393 // now append the shader text itself
4394 vertstrings_list[vertstrings_count++] = vertexstring;
4395 geomstrings_list[geomstrings_count++] = geometrystring;
4396 fragstrings_list[fragstrings_count++] = fragmentstring;
4398 // if any sources were NULL, clear the respective list
4400 vertstrings_count = 0;
4401 if (!geometrystring)
4402 geomstrings_count = 0;
4403 if (!fragmentstring)
4404 fragstrings_count = 0;
4406 vertstring_length = 0;
4407 for (i = 0;i < vertstrings_count;i++)
4408 vertstring_length += strlen(vertstrings_list[i]);
4409 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4410 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4411 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4413 geomstring_length = 0;
4414 for (i = 0;i < geomstrings_count;i++)
4415 geomstring_length += strlen(geomstrings_list[i]);
4416 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4417 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4418 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4420 fragstring_length = 0;
4421 for (i = 0;i < fragstrings_count;i++)
4422 fragstring_length += strlen(fragstrings_list[i]);
4423 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4424 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4425 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4427 // try to load the cached shader, or generate one
4428 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4430 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4431 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4433 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
4437 Mem_Free(vertstring);
4439 Mem_Free(geomstring);
4441 Mem_Free(fragstring);
4443 Mem_Free(vertexstring);
4445 Mem_Free(geometrystring);
4447 Mem_Free(fragmentstring);
4450 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4451 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4452 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);}
4453 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);}
4454 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);}
4455 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);}
4457 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4458 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4459 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);}
4460 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);}
4461 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);}
4462 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);}
4464 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4466 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4467 if (r_hlsl_permutation != perm)
4469 r_hlsl_permutation = perm;
4470 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4472 if (!r_hlsl_permutation->compiled)
4473 R_HLSL_CompilePermutation(perm, mode, permutation);
4474 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4476 // remove features until we find a valid permutation
4478 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4480 // reduce i more quickly whenever it would not remove any bits
4481 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4482 if (!(permutation & j))
4485 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4486 if (!r_hlsl_permutation->compiled)
4487 R_HLSL_CompilePermutation(perm, mode, permutation);
4488 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4491 if (i >= SHADERPERMUTATION_COUNT)
4493 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4494 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4495 return; // no bit left to clear, entire mode is broken
4499 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4500 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4502 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4503 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4504 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4508 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
4510 DPSOFTRAST_SetShader(mode, permutation);
4511 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
4512 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
4513 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
4516 void R_GLSL_Restart_f(void)
4518 unsigned int i, limit;
4519 if (glslshaderstring && glslshaderstring != builtinshaderstring)
4520 Mem_Free(glslshaderstring);
4521 glslshaderstring = NULL;
4522 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
4523 Mem_Free(hlslshaderstring);
4524 hlslshaderstring = NULL;
4525 switch(vid.renderpath)
4527 case RENDERPATH_D3D9:
4530 r_hlsl_permutation_t *p;
4531 r_hlsl_permutation = NULL;
4532 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
4533 for (i = 0;i < limit;i++)
4535 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
4537 if (p->vertexshader)
4538 IDirect3DVertexShader9_Release(p->vertexshader);
4540 IDirect3DPixelShader9_Release(p->pixelshader);
4541 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
4544 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4548 case RENDERPATH_D3D10:
4549 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4551 case RENDERPATH_D3D11:
4552 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4554 case RENDERPATH_GL20:
4555 case RENDERPATH_GLES2:
4557 r_glsl_permutation_t *p;
4558 r_glsl_permutation = NULL;
4559 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4560 for (i = 0;i < limit;i++)
4562 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4564 GL_Backend_FreeProgram(p->program);
4565 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4568 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4571 case RENDERPATH_GL13:
4572 case RENDERPATH_GL11:
4574 case RENDERPATH_SOFT:
4579 void R_GLSL_DumpShader_f(void)
4584 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4587 FS_Print(file, "/* The engine may define the following macros:\n");
4588 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4589 for (i = 0;i < SHADERMODE_COUNT;i++)
4590 FS_Print(file, glslshadermodeinfo[i].pretext);
4591 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4592 FS_Print(file, shaderpermutationinfo[i].pretext);
4593 FS_Print(file, "*/\n");
4594 FS_Print(file, builtinshaderstring);
4596 Con_Printf("glsl/default.glsl written\n");
4599 Con_Printf("failed to write to glsl/default.glsl\n");
4601 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
4604 FS_Print(file, "/* The engine may define the following macros:\n");
4605 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4606 for (i = 0;i < SHADERMODE_COUNT;i++)
4607 FS_Print(file, hlslshadermodeinfo[i].pretext);
4608 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4609 FS_Print(file, shaderpermutationinfo[i].pretext);
4610 FS_Print(file, "*/\n");
4611 FS_Print(file, builtinhlslshaderstring);
4613 Con_Printf("hlsl/default.hlsl written\n");
4616 Con_Printf("failed to write to hlsl/default.hlsl\n");
4619 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4622 texturemode = GL_MODULATE;
4623 switch (vid.renderpath)
4625 case RENDERPATH_D3D9:
4627 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))));
4628 R_Mesh_TexBind(GL20TU_FIRST , first );
4629 R_Mesh_TexBind(GL20TU_SECOND, second);
4632 case RENDERPATH_D3D10:
4633 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4635 case RENDERPATH_D3D11:
4636 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4638 case RENDERPATH_GL20:
4639 case RENDERPATH_GLES2:
4640 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))));
4641 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
4642 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
4644 case RENDERPATH_GL13:
4645 R_Mesh_TexBind(0, first );
4646 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4647 R_Mesh_TexBind(1, second);
4649 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4651 case RENDERPATH_GL11:
4652 R_Mesh_TexBind(0, first );
4654 case RENDERPATH_SOFT:
4655 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))));
4656 R_Mesh_TexBind(GL20TU_FIRST , first );
4657 R_Mesh_TexBind(GL20TU_SECOND, second);
4662 void R_SetupShader_DepthOrShadow(void)
4664 switch (vid.renderpath)
4666 case RENDERPATH_D3D9:
4668 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4671 case RENDERPATH_D3D10:
4672 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4674 case RENDERPATH_D3D11:
4675 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4677 case RENDERPATH_GL20:
4678 case RENDERPATH_GLES2:
4679 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4681 case RENDERPATH_GL13:
4682 R_Mesh_TexBind(0, 0);
4683 R_Mesh_TexBind(1, 0);
4685 case RENDERPATH_GL11:
4686 R_Mesh_TexBind(0, 0);
4688 case RENDERPATH_SOFT:
4689 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
4694 void R_SetupShader_ShowDepth(void)
4696 switch (vid.renderpath)
4698 case RENDERPATH_D3D9:
4700 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
4703 case RENDERPATH_D3D10:
4704 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4706 case RENDERPATH_D3D11:
4707 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4709 case RENDERPATH_GL20:
4710 case RENDERPATH_GLES2:
4711 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4713 case RENDERPATH_GL13:
4715 case RENDERPATH_GL11:
4717 case RENDERPATH_SOFT:
4718 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
4723 extern qboolean r_shadow_usingdeferredprepass;
4724 extern cvar_t r_shadow_deferred_8bitrange;
4725 extern rtexture_t *r_shadow_attenuationgradienttexture;
4726 extern rtexture_t *r_shadow_attenuation2dtexture;
4727 extern rtexture_t *r_shadow_attenuation3dtexture;
4728 extern qboolean r_shadow_usingshadowmap2d;
4729 extern qboolean r_shadow_usingshadowmaportho;
4730 extern float r_shadow_shadowmap_texturescale[2];
4731 extern float r_shadow_shadowmap_parameters[4];
4732 extern qboolean r_shadow_shadowmapvsdct;
4733 extern qboolean r_shadow_shadowmapsampler;
4734 extern int r_shadow_shadowmappcf;
4735 extern rtexture_t *r_shadow_shadowmap2dtexture;
4736 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
4737 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4738 extern matrix4x4_t r_shadow_shadowmapmatrix;
4739 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4740 extern int r_shadow_prepass_width;
4741 extern int r_shadow_prepass_height;
4742 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4743 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4744 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
4745 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4746 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4747 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
4749 // a blendfunc allows colormod if:
4750 // a) it can never keep the destination pixel invariant, or
4751 // b) it can keep the destination pixel invariant, and still can do so if colormodded
4752 // this is to prevent unintended side effects from colormod
4755 // IF there is a (s, sa) for which for all (d, da),
4756 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
4757 // THEN, for this (s, sa) and all (colormod, d, da):
4758 // s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
4759 // OBVIOUSLY, this means that
4760 // s*colormod * src(s*colormod, d, sa, da) = 0
4761 // dst(s*colormod, d, sa, da) = 1
4763 // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
4765 // main condition to leave dst color invariant:
4766 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
4768 // s * 0 + d * dst(s, d, sa, da) == d
4769 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4770 // => colormod is a problem for GL_SRC_COLOR only
4772 // s + d * dst(s, d, sa, da) == d
4774 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4775 // => colormod is never problematic for these
4776 // src == GL_SRC_COLOR:
4777 // s*s + d * dst(s, d, sa, da) == d
4779 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4780 // => colormod is never problematic for these
4781 // src == GL_ONE_MINUS_SRC_COLOR:
4782 // s*(1-s) + d * dst(s, d, sa, da) == d
4783 // => s == 0 or s == 1
4784 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4785 // => colormod is a problem for GL_SRC_COLOR only
4786 // src == GL_DST_COLOR
4787 // s*d + d * dst(s, d, sa, da) == d
4789 // => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4790 // => colormod is always a problem
4793 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4794 // => colormod is never problematic for these
4795 // => BUT, we do not know s! We must assume it is problematic
4796 // then... except in GL_ONE case, where we know all invariant
4798 // src == GL_ONE_MINUS_DST_COLOR
4799 // s*(1-d) + d * dst(s, d, sa, da) == d
4800 // => s == 0 (1-d is impossible to handle for our desired result)
4801 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4802 // => colormod is never problematic for these
4803 // src == GL_SRC_ALPHA
4804 // s*sa + d * dst(s, d, sa, da) == d
4805 // => s == 0, or sa == 0
4806 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4807 // => colormod breaks in the case GL_SRC_COLOR only
4808 // src == GL_ONE_MINUS_SRC_ALPHA
4809 // s*(1-sa) + d * dst(s, d, sa, da) == d
4810 // => s == 0, or sa == 1
4811 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4812 // => colormod breaks in the case GL_SRC_COLOR only
4813 // src == GL_DST_ALPHA
4814 // s*da + d * dst(s, d, sa, da) == d
4816 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4817 // => colormod is never problematic for these
4822 case GL_ONE_MINUS_SRC_COLOR:
4824 case GL_ONE_MINUS_SRC_ALPHA:
4825 if(dst == GL_SRC_COLOR)
4830 case GL_ONE_MINUS_DST_COLOR:
4832 case GL_ONE_MINUS_DST_ALPHA:
4842 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)
4844 // select a permutation of the lighting shader appropriate to this
4845 // combination of texture, entity, light source, and fogging, only use the
4846 // minimum features necessary to avoid wasting rendering time in the
4847 // fragment shader on features that are not being used
4848 unsigned int permutation = 0;
4849 unsigned int mode = 0;
4850 qboolean allow_colormod;
4851 static float dummy_colormod[3] = {1, 1, 1};
4852 float *colormod = rsurface.colormod;
4854 matrix4x4_t tempmatrix;
4855 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
4856 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4857 permutation |= SHADERPERMUTATION_ALPHAKILL;
4858 if (rsurfacepass == RSURFPASS_BACKGROUND)
4860 // distorted background
4861 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4863 mode = SHADERMODE_WATER;
4864 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
4865 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
4866 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
4868 // this is the right thing to do for wateralpha
4869 GL_BlendFunc(GL_ONE, GL_ZERO);
4870 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4874 // this is the right thing to do for entity alpha
4875 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4876 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4879 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
4881 mode = SHADERMODE_REFRACTION;
4882 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4883 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4887 mode = SHADERMODE_GENERIC;
4888 permutation |= SHADERPERMUTATION_DIFFUSE;
4889 GL_BlendFunc(GL_ONE, GL_ZERO);
4890 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4893 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4895 if (r_glsl_offsetmapping.integer)
4897 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4898 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4899 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4900 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4901 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4903 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4904 if (r_glsl_offsetmapping_reliefmapping.integer)
4905 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4908 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4909 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4910 // normalmap (deferred prepass), may use alpha test on diffuse
4911 mode = SHADERMODE_DEFERREDGEOMETRY;
4912 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4913 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4914 GL_BlendFunc(GL_ONE, GL_ZERO);
4915 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4917 else if (rsurfacepass == RSURFPASS_RTLIGHT)
4919 if (r_glsl_offsetmapping.integer)
4921 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4922 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4923 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4924 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4925 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4927 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4928 if (r_glsl_offsetmapping_reliefmapping.integer)
4929 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4932 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4933 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4935 mode = SHADERMODE_LIGHTSOURCE;
4936 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4937 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4938 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4939 permutation |= SHADERPERMUTATION_CUBEFILTER;
4940 if (diffusescale > 0)
4941 permutation |= SHADERPERMUTATION_DIFFUSE;
4942 if (specularscale > 0)
4943 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4944 if (r_refdef.fogenabled)
4945 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4946 if (rsurface.texture->colormapping)
4947 permutation |= SHADERPERMUTATION_COLORMAPPING;
4948 if (r_shadow_usingshadowmap2d)
4950 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4951 if(r_shadow_shadowmapvsdct)
4952 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4954 if (r_shadow_shadowmapsampler)
4955 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4956 if (r_shadow_shadowmappcf > 1)
4957 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4958 else if (r_shadow_shadowmappcf)
4959 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4961 if (rsurface.texture->reflectmasktexture)
4962 permutation |= SHADERPERMUTATION_REFLECTCUBE;
4963 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4964 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
4966 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4968 if (r_glsl_offsetmapping.integer)
4970 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4971 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4972 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4973 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4974 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4976 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4977 if (r_glsl_offsetmapping_reliefmapping.integer)
4978 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4981 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4982 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4983 // unshaded geometry (fullbright or ambient model lighting)
4984 mode = SHADERMODE_FLATCOLOR;
4985 ambientscale = diffusescale = specularscale = 0;
4986 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4987 permutation |= SHADERPERMUTATION_GLOW;
4988 if (r_refdef.fogenabled)
4989 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4990 if (rsurface.texture->colormapping)
4991 permutation |= SHADERPERMUTATION_COLORMAPPING;
4992 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4994 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4995 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4997 if (r_shadow_shadowmapsampler)
4998 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4999 if (r_shadow_shadowmappcf > 1)
5000 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5001 else if (r_shadow_shadowmappcf)
5002 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5004 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5005 permutation |= SHADERPERMUTATION_REFLECTION;
5006 if (rsurface.texture->reflectmasktexture)
5007 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5008 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5009 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5011 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5013 if (r_glsl_offsetmapping.integer)
5015 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5016 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5017 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5018 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5019 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5021 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5022 if (r_glsl_offsetmapping_reliefmapping.integer)
5023 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5026 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5027 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5028 // directional model lighting
5029 mode = SHADERMODE_LIGHTDIRECTION;
5030 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5031 permutation |= SHADERPERMUTATION_GLOW;
5032 permutation |= SHADERPERMUTATION_DIFFUSE;
5033 if (specularscale > 0)
5034 permutation |= SHADERPERMUTATION_SPECULAR;
5035 if (r_refdef.fogenabled)
5036 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5037 if (rsurface.texture->colormapping)
5038 permutation |= SHADERPERMUTATION_COLORMAPPING;
5039 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5041 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5042 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5044 if (r_shadow_shadowmapsampler)
5045 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5046 if (r_shadow_shadowmappcf > 1)
5047 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5048 else if (r_shadow_shadowmappcf)
5049 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5051 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5052 permutation |= SHADERPERMUTATION_REFLECTION;
5053 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5054 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5055 if (rsurface.texture->reflectmasktexture)
5056 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5057 if (r_shadow_bouncegridtexture)
5058 permutation |= SHADERPERMUTATION_BOUNCEGRID;
5059 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5060 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5062 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5064 if (r_glsl_offsetmapping.integer)
5066 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5067 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5068 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5069 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5070 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5072 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5073 if (r_glsl_offsetmapping_reliefmapping.integer)
5074 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5077 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5078 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5079 // ambient model lighting
5080 mode = SHADERMODE_LIGHTDIRECTION;
5081 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5082 permutation |= SHADERPERMUTATION_GLOW;
5083 if (r_refdef.fogenabled)
5084 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5085 if (rsurface.texture->colormapping)
5086 permutation |= SHADERPERMUTATION_COLORMAPPING;
5087 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5089 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5090 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5092 if (r_shadow_shadowmapsampler)
5093 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5094 if (r_shadow_shadowmappcf > 1)
5095 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5096 else if (r_shadow_shadowmappcf)
5097 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5099 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5100 permutation |= SHADERPERMUTATION_REFLECTION;
5101 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5102 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5103 if (rsurface.texture->reflectmasktexture)
5104 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5105 if (r_shadow_bouncegridtexture)
5106 permutation |= SHADERPERMUTATION_BOUNCEGRID;
5107 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5108 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5112 if (r_glsl_offsetmapping.integer)
5114 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5115 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5116 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5117 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5118 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5120 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5121 if (r_glsl_offsetmapping_reliefmapping.integer)
5122 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5125 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5126 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5128 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5129 permutation |= SHADERPERMUTATION_GLOW;
5130 if (r_refdef.fogenabled)
5131 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5132 if (rsurface.texture->colormapping)
5133 permutation |= SHADERPERMUTATION_COLORMAPPING;
5134 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5136 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5137 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5139 if (r_shadow_shadowmapsampler)
5140 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5141 if (r_shadow_shadowmappcf > 1)
5142 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5143 else if (r_shadow_shadowmappcf)
5144 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5146 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5147 permutation |= SHADERPERMUTATION_REFLECTION;
5148 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5149 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5150 if (rsurface.texture->reflectmasktexture)
5151 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5152 if (FAKELIGHT_ENABLED)
5154 // fake lightmapping (q1bsp, q3bsp, fullbright map)
5155 mode = SHADERMODE_FAKELIGHT;
5156 permutation |= SHADERPERMUTATION_DIFFUSE;
5157 if (specularscale > 0)
5158 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5160 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5162 // deluxemapping (light direction texture)
5163 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5164 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5166 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5167 permutation |= SHADERPERMUTATION_DIFFUSE;
5168 if (specularscale > 0)
5169 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5171 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5173 // fake deluxemapping (uniform light direction in tangentspace)
5174 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5175 permutation |= SHADERPERMUTATION_DIFFUSE;
5176 if (specularscale > 0)
5177 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5179 else if (rsurface.uselightmaptexture)
5181 // ordinary lightmapping (q1bsp, q3bsp)
5182 mode = SHADERMODE_LIGHTMAP;
5186 // ordinary vertex coloring (q3bsp)
5187 mode = SHADERMODE_VERTEXCOLOR;
5189 if (r_shadow_bouncegridtexture)
5190 permutation |= SHADERPERMUTATION_BOUNCEGRID;
5191 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5192 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5195 colormod = dummy_colormod;
5196 switch(vid.renderpath)
5198 case RENDERPATH_D3D9:
5200 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);
5201 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5202 R_SetupShader_SetPermutationHLSL(mode, permutation);
5203 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5204 if (mode == SHADERMODE_LIGHTSOURCE)
5206 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5207 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5211 if (mode == SHADERMODE_LIGHTDIRECTION)
5213 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5216 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5217 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5218 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5219 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5220 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5222 if (mode == SHADERMODE_LIGHTSOURCE)
5224 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5225 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5226 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5227 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5228 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5230 // additive passes are only darkened by fog, not tinted
5231 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5232 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5236 if (mode == SHADERMODE_FLATCOLOR)
5238 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5240 else if (mode == SHADERMODE_LIGHTDIRECTION)
5242 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]);
5243 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5244 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);
5245 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);
5246 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5247 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5248 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5252 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5253 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5254 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);
5255 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);
5256 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5258 // additive passes are only darkened by fog, not tinted
5259 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5260 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5262 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5263 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);
5264 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5265 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5266 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5267 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5268 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5269 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5270 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5271 if (mode == SHADERMODE_WATER)
5272 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5274 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5275 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5276 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5277 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));
5278 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5279 if (rsurface.texture->pantstexture)
5280 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5282 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5283 if (rsurface.texture->shirttexture)
5284 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5286 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5287 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5288 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5289 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5290 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5291 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5292 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5293 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5295 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5296 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5297 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5298 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5299 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5300 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5301 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5302 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5303 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5304 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5305 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5306 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5307 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5308 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5309 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5310 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5311 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5312 if (rsurfacepass == RSURFPASS_BACKGROUND)
5314 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5315 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5316 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5320 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5322 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5323 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5324 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5325 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5326 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5328 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5329 if (rsurface.rtlight)
5331 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5332 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5337 case RENDERPATH_D3D10:
5338 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5340 case RENDERPATH_D3D11:
5341 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5343 case RENDERPATH_GL20:
5344 case RENDERPATH_GLES2:
5345 if (!vid.useinterleavedarrays)
5347 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);
5348 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5349 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5350 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5351 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5352 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5353 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5354 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5358 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);
5359 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5361 R_SetupShader_SetPermutationGLSL(mode, permutation);
5362 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5363 if (mode == SHADERMODE_LIGHTSOURCE)
5365 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5366 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5367 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5368 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5369 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5370 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5372 // additive passes are only darkened by fog, not tinted
5373 if (r_glsl_permutation->loc_FogColor >= 0)
5374 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5375 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5379 if (mode == SHADERMODE_FLATCOLOR)
5381 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5383 else if (mode == SHADERMODE_LIGHTDIRECTION)
5385 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(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]);
5386 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5387 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(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);
5388 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(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);
5389 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5390 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(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]);
5391 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5395 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5396 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5397 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(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);
5398 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(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);
5399 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5401 // additive passes are only darkened by fog, not tinted
5402 if (r_glsl_permutation->loc_FogColor >= 0)
5404 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5405 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5407 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5409 if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(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);
5410 if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5411 if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5412 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(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]);
5413 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(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]);
5414 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5415 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5416 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5417 if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5419 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5420 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5421 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5422 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5423 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(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]);
5425 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5426 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(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));
5427 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5428 if (r_glsl_permutation->loc_Color_Pants >= 0)
5430 if (rsurface.texture->pantstexture)
5431 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5433 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5435 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5437 if (rsurface.texture->shirttexture)
5438 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5440 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5442 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4f(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5443 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5444 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5445 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5446 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5447 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5448 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5449 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
5450 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity);
5452 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
5453 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
5454 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
5455 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
5456 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
5457 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
5458 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
5459 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
5460 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
5461 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
5462 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
5463 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
5464 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
5465 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
5466 if (r_glsl_permutation->tex_Texture_ReflectCube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5467 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
5468 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
5469 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5470 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5471 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
5472 if (rsurfacepass == RSURFPASS_BACKGROUND)
5474 if (r_glsl_permutation->tex_Texture_Refraction >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5475 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5476 if (r_glsl_permutation->tex_Texture_Reflection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5480 if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5482 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
5483 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
5484 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
5485 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
5486 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5488 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
5489 if (rsurface.rtlight)
5491 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
5492 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
5495 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
5498 case RENDERPATH_GL13:
5499 case RENDERPATH_GL11:
5501 case RENDERPATH_SOFT:
5502 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);
5503 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
5504 R_SetupShader_SetPermutationSoft(mode, permutation);
5505 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
5506 if (mode == SHADERMODE_LIGHTSOURCE)
5508 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
5509 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5510 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5511 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5512 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5513 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5515 // additive passes are only darkened by fog, not tinted
5516 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
5517 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5521 if (mode == SHADERMODE_FLATCOLOR)
5523 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5525 else if (mode == SHADERMODE_LIGHTDIRECTION)
5527 DPSOFTRAST_Uniform3f(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]);
5528 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5529 DPSOFTRAST_Uniform3f(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);
5530 DPSOFTRAST_Uniform3f(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);
5531 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5532 DPSOFTRAST_Uniform3f(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]);
5533 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5537 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5538 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5539 DPSOFTRAST_Uniform3f(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);
5540 DPSOFTRAST_Uniform3f(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);
5541 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5543 // additive passes are only darkened by fog, not tinted
5544 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5545 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
5547 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5548 DPSOFTRAST_Uniform4f(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);
5549 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5550 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5551 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5552 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5553 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5554 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
5555 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5556 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5558 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
5559 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
5560 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
5561 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5562 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5564 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5565 DPSOFTRAST_Uniform1f(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));
5566 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5567 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
5569 if (rsurface.texture->pantstexture)
5570 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5572 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
5574 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
5576 if (rsurface.texture->shirttexture)
5577 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5579 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
5581 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5582 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
5583 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
5584 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
5585 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5586 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5587 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5589 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5590 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5591 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5592 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5593 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5594 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5595 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5596 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5597 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5598 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5599 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5600 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5601 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5602 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5603 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5604 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5605 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5606 if (rsurfacepass == RSURFPASS_BACKGROUND)
5608 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5609 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5610 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5614 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5616 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5617 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5618 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5619 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5620 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5622 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5623 if (rsurface.rtlight)
5625 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5626 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5633 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5635 // select a permutation of the lighting shader appropriate to this
5636 // combination of texture, entity, light source, and fogging, only use the
5637 // minimum features necessary to avoid wasting rendering time in the
5638 // fragment shader on features that are not being used
5639 unsigned int permutation = 0;
5640 unsigned int mode = 0;
5641 const float *lightcolorbase = rtlight->currentcolor;
5642 float ambientscale = rtlight->ambientscale;
5643 float diffusescale = rtlight->diffusescale;
5644 float specularscale = rtlight->specularscale;
5645 // this is the location of the light in view space
5646 vec3_t viewlightorigin;
5647 // this transforms from view space (camera) to light space (cubemap)
5648 matrix4x4_t viewtolight;
5649 matrix4x4_t lighttoview;
5650 float viewtolight16f[16];
5651 float range = 1.0f / r_shadow_deferred_8bitrange.value;
5653 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
5654 if (rtlight->currentcubemap != r_texture_whitecube)
5655 permutation |= SHADERPERMUTATION_CUBEFILTER;
5656 if (diffusescale > 0)
5657 permutation |= SHADERPERMUTATION_DIFFUSE;
5658 if (specularscale > 0)
5659 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5660 if (r_shadow_usingshadowmap2d)
5662 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5663 if (r_shadow_shadowmapvsdct)
5664 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5666 if (r_shadow_shadowmapsampler)
5667 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5668 if (r_shadow_shadowmappcf > 1)
5669 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5670 else if (r_shadow_shadowmappcf)
5671 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5673 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
5674 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
5675 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
5676 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
5677 switch(vid.renderpath)
5679 case RENDERPATH_D3D9:
5681 R_SetupShader_SetPermutationHLSL(mode, permutation);
5682 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5683 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
5684 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
5685 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
5686 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
5687 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5688 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5689 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5690 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5691 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5693 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5694 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
5695 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5696 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5697 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
5698 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5701 case RENDERPATH_D3D10:
5702 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5704 case RENDERPATH_D3D11:
5705 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5707 case RENDERPATH_GL20:
5708 case RENDERPATH_GLES2:
5709 R_SetupShader_SetPermutationGLSL(mode, permutation);
5710 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5711 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
5712 if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
5713 if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
5714 if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
5715 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f( r_glsl_permutation->loc_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5716 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f( 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]);
5717 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f( 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));
5718 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f( r_glsl_permutation->loc_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5719 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
5721 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
5722 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
5723 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
5724 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
5725 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
5726 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
5728 case RENDERPATH_GL13:
5729 case RENDERPATH_GL11:
5731 case RENDERPATH_SOFT:
5732 R_SetupShader_SetPermutationGLSL(mode, permutation);
5733 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5734 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
5735 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
5736 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
5737 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
5738 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5739 DPSOFTRAST_Uniform4f( DPSOFTRAST_UNIFORM_ShadowMap_Parameters , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5740 DPSOFTRAST_Uniform1f( DPSOFTRAST_UNIFORM_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5741 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5742 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5744 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5745 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5746 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5747 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5748 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
5749 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5754 #define SKINFRAME_HASH 1024
5758 int loadsequence; // incremented each level change
5759 memexpandablearray_t array;
5760 skinframe_t *hash[SKINFRAME_HASH];
5763 r_skinframe_t r_skinframe;
5765 void R_SkinFrame_PrepareForPurge(void)
5767 r_skinframe.loadsequence++;
5768 // wrap it without hitting zero
5769 if (r_skinframe.loadsequence >= 200)
5770 r_skinframe.loadsequence = 1;
5773 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5777 // mark the skinframe as used for the purging code
5778 skinframe->loadsequence = r_skinframe.loadsequence;
5781 void R_SkinFrame_Purge(void)
5785 for (i = 0;i < SKINFRAME_HASH;i++)
5787 for (s = r_skinframe.hash[i];s;s = s->next)
5789 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5791 if (s->merged == s->base)
5793 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5794 R_PurgeTexture(s->stain );s->stain = NULL;
5795 R_PurgeTexture(s->merged);s->merged = NULL;
5796 R_PurgeTexture(s->base );s->base = NULL;
5797 R_PurgeTexture(s->pants );s->pants = NULL;
5798 R_PurgeTexture(s->shirt );s->shirt = NULL;
5799 R_PurgeTexture(s->nmap );s->nmap = NULL;
5800 R_PurgeTexture(s->gloss );s->gloss = NULL;
5801 R_PurgeTexture(s->glow );s->glow = NULL;
5802 R_PurgeTexture(s->fog );s->fog = NULL;
5803 R_PurgeTexture(s->reflect);s->reflect = NULL;
5804 s->loadsequence = 0;
5810 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5812 char basename[MAX_QPATH];
5814 Image_StripImageExtension(name, basename, sizeof(basename));
5816 if( last == NULL ) {
5818 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5819 item = r_skinframe.hash[hashindex];
5824 // linearly search through the hash bucket
5825 for( ; item ; item = item->next ) {
5826 if( !strcmp( item->basename, basename ) ) {
5833 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5837 char basename[MAX_QPATH];
5839 Image_StripImageExtension(name, basename, sizeof(basename));
5841 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5842 for (item = r_skinframe.hash[hashindex];item;item = item->next)
5843 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5847 rtexture_t *dyntexture;
5848 // check whether its a dynamic texture
5849 dyntexture = CL_GetDynTexture( basename );
5850 if (!add && !dyntexture)
5852 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5853 memset(item, 0, sizeof(*item));
5854 strlcpy(item->basename, basename, sizeof(item->basename));
5855 item->base = dyntexture; // either NULL or dyntexture handle
5856 item->textureflags = textureflags;
5857 item->comparewidth = comparewidth;
5858 item->compareheight = compareheight;
5859 item->comparecrc = comparecrc;
5860 item->next = r_skinframe.hash[hashindex];
5861 r_skinframe.hash[hashindex] = item;
5863 else if( item->base == NULL )
5865 rtexture_t *dyntexture;
5866 // check whether its a dynamic texture
5867 // 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]
5868 dyntexture = CL_GetDynTexture( basename );
5869 item->base = dyntexture; // either NULL or dyntexture handle
5872 R_SkinFrame_MarkUsed(item);
5876 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5878 unsigned long long avgcolor[5], wsum; \
5886 for(pix = 0; pix < cnt; ++pix) \
5889 for(comp = 0; comp < 3; ++comp) \
5891 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5894 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5896 for(comp = 0; comp < 3; ++comp) \
5897 avgcolor[comp] += getpixel * w; \
5900 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5901 avgcolor[4] += getpixel; \
5903 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5905 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5906 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5907 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5908 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5911 extern cvar_t gl_picmip;
5912 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5915 unsigned char *pixels;
5916 unsigned char *bumppixels;
5917 unsigned char *basepixels = NULL;
5918 int basepixels_width = 0;
5919 int basepixels_height = 0;
5920 skinframe_t *skinframe;
5921 rtexture_t *ddsbase = NULL;
5922 qboolean ddshasalpha = false;
5923 float ddsavgcolor[4];
5924 char basename[MAX_QPATH];
5925 int miplevel = R_PicmipForFlags(textureflags);
5926 int savemiplevel = miplevel;
5929 if (cls.state == ca_dedicated)
5932 // return an existing skinframe if already loaded
5933 // if loading of the first image fails, don't make a new skinframe as it
5934 // would cause all future lookups of this to be missing
5935 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5936 if (skinframe && skinframe->base)
5939 Image_StripImageExtension(name, basename, sizeof(basename));
5941 // check for DDS texture file first
5942 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
5944 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
5945 if (basepixels == NULL)
5949 // FIXME handle miplevel
5951 if (developer_loading.integer)
5952 Con_Printf("loading skin \"%s\"\n", name);
5954 // we've got some pixels to store, so really allocate this new texture now
5956 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5957 skinframe->stain = NULL;
5958 skinframe->merged = NULL;
5959 skinframe->base = NULL;
5960 skinframe->pants = NULL;
5961 skinframe->shirt = NULL;
5962 skinframe->nmap = NULL;
5963 skinframe->gloss = NULL;
5964 skinframe->glow = NULL;
5965 skinframe->fog = NULL;
5966 skinframe->reflect = NULL;
5967 skinframe->hasalpha = false;
5971 skinframe->base = ddsbase;
5972 skinframe->hasalpha = ddshasalpha;
5973 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5974 if (r_loadfog && skinframe->hasalpha)
5975 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
5976 //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]);
5980 basepixels_width = image_width;
5981 basepixels_height = image_height;
5982 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);
5983 if (textureflags & TEXF_ALPHA)
5985 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5987 if (basepixels[j] < 255)
5989 skinframe->hasalpha = true;
5993 if (r_loadfog && skinframe->hasalpha)
5995 // has transparent pixels
5996 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5997 for (j = 0;j < image_width * image_height * 4;j += 4)
6002 pixels[j+3] = basepixels[j+3];
6004 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);
6008 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6009 //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]);
6010 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6011 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6012 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6013 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6018 mymiplevel = savemiplevel;
6019 if (r_loadnormalmap)
6020 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);
6021 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6023 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6024 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6025 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6026 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6029 // _norm is the name used by tenebrae and has been adopted as standard
6030 if (r_loadnormalmap && skinframe->nmap == NULL)
6032 mymiplevel = savemiplevel;
6033 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6035 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);
6039 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6041 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6042 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6043 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);
6045 Mem_Free(bumppixels);
6047 else if (r_shadow_bumpscale_basetexture.value > 0)
6049 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6050 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6051 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);
6054 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6055 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6058 // _luma is supported only for tenebrae compatibility
6059 // _glow is the preferred name
6060 mymiplevel = savemiplevel;
6061 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))))
6063 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);
6064 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6065 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6066 Mem_Free(pixels);pixels = NULL;
6069 mymiplevel = savemiplevel;
6070 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6072 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);
6073 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6074 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6079 mymiplevel = savemiplevel;
6080 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6082 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);
6083 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6084 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6089 mymiplevel = savemiplevel;
6090 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6092 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);
6093 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6094 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6099 mymiplevel = savemiplevel;
6100 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6102 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);
6103 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6104 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6110 Mem_Free(basepixels);
6115 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6116 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6119 unsigned char *temp1, *temp2;
6120 skinframe_t *skinframe;
6122 if (cls.state == ca_dedicated)
6125 // if already loaded just return it, otherwise make a new skinframe
6126 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6127 if (skinframe && skinframe->base)
6130 skinframe->stain = NULL;
6131 skinframe->merged = NULL;
6132 skinframe->base = NULL;
6133 skinframe->pants = NULL;
6134 skinframe->shirt = NULL;
6135 skinframe->nmap = NULL;
6136 skinframe->gloss = NULL;
6137 skinframe->glow = NULL;
6138 skinframe->fog = NULL;
6139 skinframe->reflect = NULL;
6140 skinframe->hasalpha = false;
6142 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6146 if (developer_loading.integer)
6147 Con_Printf("loading 32bit skin \"%s\"\n", name);
6149 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6151 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6152 temp2 = temp1 + width * height * 4;
6153 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6154 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);
6157 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6158 if (textureflags & TEXF_ALPHA)
6160 for (i = 3;i < width * height * 4;i += 4)
6162 if (skindata[i] < 255)
6164 skinframe->hasalpha = true;
6168 if (r_loadfog && skinframe->hasalpha)
6170 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6171 memcpy(fogpixels, skindata, width * height * 4);
6172 for (i = 0;i < width * height * 4;i += 4)
6173 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6174 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6175 Mem_Free(fogpixels);
6179 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6180 //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]);
6185 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6189 skinframe_t *skinframe;
6191 if (cls.state == ca_dedicated)
6194 // if already loaded just return it, otherwise make a new skinframe
6195 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6196 if (skinframe && skinframe->base)
6199 skinframe->stain = NULL;
6200 skinframe->merged = NULL;
6201 skinframe->base = NULL;
6202 skinframe->pants = NULL;
6203 skinframe->shirt = NULL;
6204 skinframe->nmap = NULL;
6205 skinframe->gloss = NULL;
6206 skinframe->glow = NULL;
6207 skinframe->fog = NULL;
6208 skinframe->reflect = NULL;
6209 skinframe->hasalpha = false;
6211 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6215 if (developer_loading.integer)
6216 Con_Printf("loading quake skin \"%s\"\n", name);
6218 // 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)
6219 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
6220 memcpy(skinframe->qpixels, skindata, width*height);
6221 skinframe->qwidth = width;
6222 skinframe->qheight = height;
6225 for (i = 0;i < width * height;i++)
6226 featuresmask |= palette_featureflags[skindata[i]];
6228 skinframe->hasalpha = false;
6229 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6230 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6231 skinframe->qgeneratemerged = true;
6232 skinframe->qgeneratebase = skinframe->qhascolormapping;
6233 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6235 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6236 //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]);
6241 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6245 unsigned char *skindata;
6247 if (!skinframe->qpixels)
6250 if (!skinframe->qhascolormapping)
6251 colormapped = false;
6255 if (!skinframe->qgeneratebase)
6260 if (!skinframe->qgeneratemerged)
6264 width = skinframe->qwidth;
6265 height = skinframe->qheight;
6266 skindata = skinframe->qpixels;
6268 if (skinframe->qgeneratenmap)
6270 unsigned char *temp1, *temp2;
6271 skinframe->qgeneratenmap = false;
6272 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6273 temp2 = temp1 + width * height * 4;
6274 // use either a custom palette or the quake palette
6275 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6276 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6277 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);
6281 if (skinframe->qgenerateglow)
6283 skinframe->qgenerateglow = false;
6284 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6289 skinframe->qgeneratebase = false;
6290 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);
6291 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6292 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6296 skinframe->qgeneratemerged = false;
6297 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);
6300 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6302 Mem_Free(skinframe->qpixels);
6303 skinframe->qpixels = NULL;
6307 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)
6310 skinframe_t *skinframe;
6312 if (cls.state == ca_dedicated)
6315 // if already loaded just return it, otherwise make a new skinframe
6316 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6317 if (skinframe && skinframe->base)
6320 skinframe->stain = NULL;
6321 skinframe->merged = NULL;
6322 skinframe->base = NULL;
6323 skinframe->pants = NULL;
6324 skinframe->shirt = NULL;
6325 skinframe->nmap = NULL;
6326 skinframe->gloss = NULL;
6327 skinframe->glow = NULL;
6328 skinframe->fog = NULL;
6329 skinframe->reflect = NULL;
6330 skinframe->hasalpha = false;
6332 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6336 if (developer_loading.integer)
6337 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6339 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6340 if (textureflags & TEXF_ALPHA)
6342 for (i = 0;i < width * height;i++)
6344 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6346 skinframe->hasalpha = true;
6350 if (r_loadfog && skinframe->hasalpha)
6351 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6354 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6355 //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]);
6360 skinframe_t *R_SkinFrame_LoadMissing(void)
6362 skinframe_t *skinframe;
6364 if (cls.state == ca_dedicated)
6367 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6368 skinframe->stain = NULL;
6369 skinframe->merged = NULL;
6370 skinframe->base = NULL;
6371 skinframe->pants = NULL;
6372 skinframe->shirt = NULL;
6373 skinframe->nmap = NULL;
6374 skinframe->gloss = NULL;
6375 skinframe->glow = NULL;
6376 skinframe->fog = NULL;
6377 skinframe->reflect = NULL;
6378 skinframe->hasalpha = false;
6380 skinframe->avgcolor[0] = rand() / RAND_MAX;
6381 skinframe->avgcolor[1] = rand() / RAND_MAX;
6382 skinframe->avgcolor[2] = rand() / RAND_MAX;
6383 skinframe->avgcolor[3] = 1;
6388 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6389 typedef struct suffixinfo_s
6392 qboolean flipx, flipy, flipdiagonal;
6395 static suffixinfo_t suffix[3][6] =
6398 {"px", false, false, false},
6399 {"nx", false, false, false},
6400 {"py", false, false, false},
6401 {"ny", false, false, false},
6402 {"pz", false, false, false},
6403 {"nz", false, false, false}
6406 {"posx", false, false, false},
6407 {"negx", false, false, false},
6408 {"posy", false, false, false},
6409 {"negy", false, false, false},
6410 {"posz", false, false, false},
6411 {"negz", false, false, false}
6414 {"rt", true, false, true},
6415 {"lf", false, true, true},
6416 {"ft", true, true, false},
6417 {"bk", false, false, false},
6418 {"up", true, false, true},
6419 {"dn", true, false, true}
6423 static int componentorder[4] = {0, 1, 2, 3};
6425 rtexture_t *R_LoadCubemap(const char *basename)
6427 int i, j, cubemapsize;
6428 unsigned char *cubemappixels, *image_buffer;
6429 rtexture_t *cubemaptexture;
6431 // must start 0 so the first loadimagepixels has no requested width/height
6433 cubemappixels = NULL;
6434 cubemaptexture = NULL;
6435 // keep trying different suffix groups (posx, px, rt) until one loads
6436 for (j = 0;j < 3 && !cubemappixels;j++)
6438 // load the 6 images in the suffix group
6439 for (i = 0;i < 6;i++)
6441 // generate an image name based on the base and and suffix
6442 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6444 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
6446 // an image loaded, make sure width and height are equal
6447 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6449 // if this is the first image to load successfully, allocate the cubemap memory
6450 if (!cubemappixels && image_width >= 1)
6452 cubemapsize = image_width;
6453 // note this clears to black, so unavailable sides are black
6454 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6456 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6458 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);
6461 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6463 Mem_Free(image_buffer);
6467 // if a cubemap loaded, upload it
6470 if (developer_loading.integer)
6471 Con_Printf("loading cubemap \"%s\"\n", basename);
6473 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6474 Mem_Free(cubemappixels);
6478 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6479 if (developer_loading.integer)
6481 Con_Printf("(tried tried images ");
6482 for (j = 0;j < 3;j++)
6483 for (i = 0;i < 6;i++)
6484 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6485 Con_Print(" and was unable to find any of them).\n");
6488 return cubemaptexture;
6491 rtexture_t *R_GetCubemap(const char *basename)
6494 for (i = 0;i < r_texture_numcubemaps;i++)
6495 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6496 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6497 if (i >= MAX_CUBEMAPS)
6498 return r_texture_whitecube;
6499 r_texture_numcubemaps++;
6500 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6501 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6502 return r_texture_cubemaps[i].texture;
6505 void R_FreeCubemaps(void)
6508 for (i = 0;i < r_texture_numcubemaps;i++)
6510 if (developer_loading.integer)
6511 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6512 if (r_texture_cubemaps[i].texture)
6513 R_FreeTexture(r_texture_cubemaps[i].texture);
6515 r_texture_numcubemaps = 0;
6518 void R_Main_FreeViewCache(void)
6520 if (r_refdef.viewcache.entityvisible)
6521 Mem_Free(r_refdef.viewcache.entityvisible);
6522 if (r_refdef.viewcache.world_pvsbits)
6523 Mem_Free(r_refdef.viewcache.world_pvsbits);
6524 if (r_refdef.viewcache.world_leafvisible)
6525 Mem_Free(r_refdef.viewcache.world_leafvisible);
6526 if (r_refdef.viewcache.world_surfacevisible)
6527 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6528 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6531 void R_Main_ResizeViewCache(void)
6533 int numentities = r_refdef.scene.numentities;
6534 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6535 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6536 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6537 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6538 if (r_refdef.viewcache.maxentities < numentities)
6540 r_refdef.viewcache.maxentities = numentities;
6541 if (r_refdef.viewcache.entityvisible)
6542 Mem_Free(r_refdef.viewcache.entityvisible);
6543 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6545 if (r_refdef.viewcache.world_numclusters != numclusters)
6547 r_refdef.viewcache.world_numclusters = numclusters;
6548 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6549 if (r_refdef.viewcache.world_pvsbits)
6550 Mem_Free(r_refdef.viewcache.world_pvsbits);
6551 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6553 if (r_refdef.viewcache.world_numleafs != numleafs)
6555 r_refdef.viewcache.world_numleafs = numleafs;
6556 if (r_refdef.viewcache.world_leafvisible)
6557 Mem_Free(r_refdef.viewcache.world_leafvisible);
6558 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6560 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6562 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6563 if (r_refdef.viewcache.world_surfacevisible)
6564 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6565 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6569 extern rtexture_t *loadingscreentexture;
6570 void gl_main_start(void)
6572 loadingscreentexture = NULL;
6573 r_texture_blanknormalmap = NULL;
6574 r_texture_white = NULL;
6575 r_texture_grey128 = NULL;
6576 r_texture_black = NULL;
6577 r_texture_whitecube = NULL;
6578 r_texture_normalizationcube = NULL;
6579 r_texture_fogattenuation = NULL;
6580 r_texture_fogheighttexture = NULL;
6581 r_texture_gammaramps = NULL;
6582 r_texture_numcubemaps = 0;
6584 r_loaddds = r_texture_dds_load.integer != 0;
6585 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6587 switch(vid.renderpath)
6589 case RENDERPATH_GL20:
6590 case RENDERPATH_D3D9:
6591 case RENDERPATH_D3D10:
6592 case RENDERPATH_D3D11:
6593 case RENDERPATH_SOFT:
6594 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6595 Cvar_SetValueQuick(&gl_combine, 1);
6596 Cvar_SetValueQuick(&r_glsl, 1);
6597 r_loadnormalmap = true;
6601 case RENDERPATH_GL13:
6602 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6603 Cvar_SetValueQuick(&gl_combine, 1);
6604 Cvar_SetValueQuick(&r_glsl, 0);
6605 r_loadnormalmap = false;
6606 r_loadgloss = false;
6609 case RENDERPATH_GL11:
6610 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6611 Cvar_SetValueQuick(&gl_combine, 0);
6612 Cvar_SetValueQuick(&r_glsl, 0);
6613 r_loadnormalmap = false;
6614 r_loadgloss = false;
6617 case RENDERPATH_GLES2:
6618 Cvar_SetValueQuick(&r_textureunits, 1);
6619 Cvar_SetValueQuick(&gl_combine, 1);
6620 Cvar_SetValueQuick(&r_glsl, 1);
6621 r_loadnormalmap = true;
6622 r_loadgloss = false;
6628 R_FrameData_Reset();
6632 memset(r_queries, 0, sizeof(r_queries));
6634 r_qwskincache = NULL;
6635 r_qwskincache_size = 0;
6637 // set up r_skinframe loading system for textures
6638 memset(&r_skinframe, 0, sizeof(r_skinframe));
6639 r_skinframe.loadsequence = 1;
6640 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6642 r_main_texturepool = R_AllocTexturePool();
6643 R_BuildBlankTextures();
6645 if (vid.support.arb_texture_cube_map)
6648 R_BuildNormalizationCube();
6650 r_texture_fogattenuation = NULL;
6651 r_texture_fogheighttexture = NULL;
6652 r_texture_gammaramps = NULL;
6653 //r_texture_fogintensity = NULL;
6654 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6655 memset(&r_waterstate, 0, sizeof(r_waterstate));
6656 r_glsl_permutation = NULL;
6657 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6658 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
6659 glslshaderstring = NULL;
6661 r_hlsl_permutation = NULL;
6662 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
6663 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
6665 hlslshaderstring = NULL;
6666 memset(&r_svbsp, 0, sizeof (r_svbsp));
6668 r_refdef.fogmasktable_density = 0;
6671 void gl_main_shutdown(void)
6674 R_FrameData_Reset();
6676 R_Main_FreeViewCache();
6678 switch(vid.renderpath)
6680 case RENDERPATH_GL11:
6681 case RENDERPATH_GL13:
6682 case RENDERPATH_GL20:
6683 case RENDERPATH_GLES2:
6685 qglDeleteQueriesARB(r_maxqueries, r_queries);
6687 case RENDERPATH_D3D9:
6688 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6690 case RENDERPATH_D3D10:
6691 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6693 case RENDERPATH_D3D11:
6694 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6696 case RENDERPATH_SOFT:
6702 memset(r_queries, 0, sizeof(r_queries));
6704 r_qwskincache = NULL;
6705 r_qwskincache_size = 0;
6707 // clear out the r_skinframe state
6708 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
6709 memset(&r_skinframe, 0, sizeof(r_skinframe));
6712 Mem_Free(r_svbsp.nodes);
6713 memset(&r_svbsp, 0, sizeof (r_svbsp));
6714 R_FreeTexturePool(&r_main_texturepool);
6715 loadingscreentexture = NULL;
6716 r_texture_blanknormalmap = NULL;
6717 r_texture_white = NULL;
6718 r_texture_grey128 = NULL;
6719 r_texture_black = NULL;
6720 r_texture_whitecube = NULL;
6721 r_texture_normalizationcube = NULL;
6722 r_texture_fogattenuation = NULL;
6723 r_texture_fogheighttexture = NULL;
6724 r_texture_gammaramps = NULL;
6725 r_texture_numcubemaps = 0;
6726 //r_texture_fogintensity = NULL;
6727 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6728 memset(&r_waterstate, 0, sizeof(r_waterstate));
6731 r_glsl_permutation = NULL;
6732 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6733 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
6734 glslshaderstring = NULL;
6736 r_hlsl_permutation = NULL;
6737 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
6738 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
6740 hlslshaderstring = NULL;
6743 extern void CL_ParseEntityLump(char *entitystring);
6744 void gl_main_newmap(void)
6746 // FIXME: move this code to client
6747 char *entities, entname[MAX_QPATH];
6749 Mem_Free(r_qwskincache);
6750 r_qwskincache = NULL;
6751 r_qwskincache_size = 0;
6754 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
6755 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
6757 CL_ParseEntityLump(entities);
6761 if (cl.worldmodel->brush.entities)
6762 CL_ParseEntityLump(cl.worldmodel->brush.entities);
6764 R_Main_FreeViewCache();
6766 R_FrameData_Reset();
6769 void GL_Main_Init(void)
6771 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
6773 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
6774 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
6775 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
6776 if (gamemode == GAME_NEHAHRA)
6778 Cvar_RegisterVariable (&gl_fogenable);
6779 Cvar_RegisterVariable (&gl_fogdensity);
6780 Cvar_RegisterVariable (&gl_fogred);
6781 Cvar_RegisterVariable (&gl_foggreen);
6782 Cvar_RegisterVariable (&gl_fogblue);
6783 Cvar_RegisterVariable (&gl_fogstart);
6784 Cvar_RegisterVariable (&gl_fogend);
6785 Cvar_RegisterVariable (&gl_skyclip);
6787 Cvar_RegisterVariable(&r_motionblur);
6788 Cvar_RegisterVariable(&r_motionblur_maxblur);
6789 Cvar_RegisterVariable(&r_motionblur_bmin);
6790 Cvar_RegisterVariable(&r_motionblur_vmin);
6791 Cvar_RegisterVariable(&r_motionblur_vmax);
6792 Cvar_RegisterVariable(&r_motionblur_vcoeff);
6793 Cvar_RegisterVariable(&r_motionblur_randomize);
6794 Cvar_RegisterVariable(&r_damageblur);
6795 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
6796 Cvar_RegisterVariable(&r_equalize_entities_minambient);
6797 Cvar_RegisterVariable(&r_equalize_entities_by);
6798 Cvar_RegisterVariable(&r_equalize_entities_to);
6799 Cvar_RegisterVariable(&r_depthfirst);
6800 Cvar_RegisterVariable(&r_useinfinitefarclip);
6801 Cvar_RegisterVariable(&r_farclip_base);
6802 Cvar_RegisterVariable(&r_farclip_world);
6803 Cvar_RegisterVariable(&r_nearclip);
6804 Cvar_RegisterVariable(&r_showbboxes);
6805 Cvar_RegisterVariable(&r_showsurfaces);
6806 Cvar_RegisterVariable(&r_showtris);
6807 Cvar_RegisterVariable(&r_shownormals);
6808 Cvar_RegisterVariable(&r_showlighting);
6809 Cvar_RegisterVariable(&r_showshadowvolumes);
6810 Cvar_RegisterVariable(&r_showcollisionbrushes);
6811 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
6812 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
6813 Cvar_RegisterVariable(&r_showdisabledepthtest);
6814 Cvar_RegisterVariable(&r_drawportals);
6815 Cvar_RegisterVariable(&r_drawentities);
6816 Cvar_RegisterVariable(&r_draw2d);
6817 Cvar_RegisterVariable(&r_drawworld);
6818 Cvar_RegisterVariable(&r_cullentities_trace);
6819 Cvar_RegisterVariable(&r_cullentities_trace_samples);
6820 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
6821 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
6822 Cvar_RegisterVariable(&r_cullentities_trace_delay);
6823 Cvar_RegisterVariable(&r_drawviewmodel);
6824 Cvar_RegisterVariable(&r_drawexteriormodel);
6825 Cvar_RegisterVariable(&r_speeds);
6826 Cvar_RegisterVariable(&r_fullbrights);
6827 Cvar_RegisterVariable(&r_wateralpha);
6828 Cvar_RegisterVariable(&r_dynamic);
6829 Cvar_RegisterVariable(&r_fakelight);
6830 Cvar_RegisterVariable(&r_fakelight_intensity);
6831 Cvar_RegisterVariable(&r_fullbright);
6832 Cvar_RegisterVariable(&r_shadows);
6833 Cvar_RegisterVariable(&r_shadows_darken);
6834 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
6835 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
6836 Cvar_RegisterVariable(&r_shadows_throwdistance);
6837 Cvar_RegisterVariable(&r_shadows_throwdirection);
6838 Cvar_RegisterVariable(&r_shadows_focus);
6839 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
6840 Cvar_RegisterVariable(&r_q1bsp_skymasking);
6841 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
6842 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
6843 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
6844 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
6845 Cvar_RegisterVariable(&r_fog_exp2);
6846 Cvar_RegisterVariable(&r_drawfog);
6847 Cvar_RegisterVariable(&r_transparentdepthmasking);
6848 Cvar_RegisterVariable(&r_texture_dds_load);
6849 Cvar_RegisterVariable(&r_texture_dds_save);
6850 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
6851 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
6852 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
6853 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
6854 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
6855 Cvar_RegisterVariable(&r_textureunits);
6856 Cvar_RegisterVariable(&gl_combine);
6857 Cvar_RegisterVariable(&r_glsl);
6858 Cvar_RegisterVariable(&r_glsl_deluxemapping);
6859 Cvar_RegisterVariable(&r_glsl_offsetmapping);
6860 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
6861 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
6862 Cvar_RegisterVariable(&r_glsl_postprocess);
6863 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
6864 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
6865 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
6866 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
6867 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
6868 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
6869 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
6870 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
6872 Cvar_RegisterVariable(&r_water);
6873 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
6874 Cvar_RegisterVariable(&r_water_clippingplanebias);
6875 Cvar_RegisterVariable(&r_water_refractdistort);
6876 Cvar_RegisterVariable(&r_water_reflectdistort);
6877 Cvar_RegisterVariable(&r_water_scissormode);
6878 Cvar_RegisterVariable(&r_lerpsprites);
6879 Cvar_RegisterVariable(&r_lerpmodels);
6880 Cvar_RegisterVariable(&r_lerplightstyles);
6881 Cvar_RegisterVariable(&r_waterscroll);
6882 Cvar_RegisterVariable(&r_bloom);
6883 Cvar_RegisterVariable(&r_bloom_colorscale);
6884 Cvar_RegisterVariable(&r_bloom_brighten);
6885 Cvar_RegisterVariable(&r_bloom_blur);
6886 Cvar_RegisterVariable(&r_bloom_resolution);
6887 Cvar_RegisterVariable(&r_bloom_colorexponent);
6888 Cvar_RegisterVariable(&r_bloom_colorsubtract);
6889 Cvar_RegisterVariable(&r_hdr);
6890 Cvar_RegisterVariable(&r_hdr_scenebrightness);
6891 Cvar_RegisterVariable(&r_hdr_glowintensity);
6892 Cvar_RegisterVariable(&r_hdr_range);
6893 Cvar_RegisterVariable(&r_hdr_irisadaptation);
6894 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
6895 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
6896 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
6897 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
6898 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
6899 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
6900 Cvar_RegisterVariable(&developer_texturelogging);
6901 Cvar_RegisterVariable(&gl_lightmaps);
6902 Cvar_RegisterVariable(&r_test);
6903 Cvar_RegisterVariable(&r_glsl_saturation);
6904 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
6905 Cvar_RegisterVariable(&r_framedatasize);
6906 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
6907 Cvar_SetValue("r_fullbrights", 0);
6908 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
6910 Cvar_RegisterVariable(&r_track_sprites);
6911 Cvar_RegisterVariable(&r_track_sprites_flags);
6912 Cvar_RegisterVariable(&r_track_sprites_scalew);
6913 Cvar_RegisterVariable(&r_track_sprites_scaleh);
6914 Cvar_RegisterVariable(&r_overheadsprites_perspective);
6915 Cvar_RegisterVariable(&r_overheadsprites_pushback);
6916 Cvar_RegisterVariable(&r_overheadsprites_scalex);
6917 Cvar_RegisterVariable(&r_overheadsprites_scaley);
6920 extern void R_Textures_Init(void);
6921 extern void GL_Draw_Init(void);
6922 extern void GL_Main_Init(void);
6923 extern void R_Shadow_Init(void);
6924 extern void R_Sky_Init(void);
6925 extern void GL_Surf_Init(void);
6926 extern void R_Particles_Init(void);
6927 extern void R_Explosion_Init(void);
6928 extern void gl_backend_init(void);
6929 extern void Sbar_Init(void);
6930 extern void R_LightningBeams_Init(void);
6931 extern void Mod_RenderInit(void);
6932 extern void Font_Init(void);
6934 void Render_Init(void)
6947 R_LightningBeams_Init();
6956 extern char *ENGINE_EXTENSIONS;
6959 gl_renderer = (const char *)qglGetString(GL_RENDERER);
6960 gl_vendor = (const char *)qglGetString(GL_VENDOR);
6961 gl_version = (const char *)qglGetString(GL_VERSION);
6962 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
6966 if (!gl_platformextensions)
6967 gl_platformextensions = "";
6969 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
6970 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
6971 Con_Printf("GL_VERSION: %s\n", gl_version);
6972 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
6973 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
6975 VID_CheckExtensions();
6977 // LordHavoc: report supported extensions
6978 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6980 // clear to black (loading plaque will be seen over this)
6981 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6984 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6988 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6990 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6993 p = r_refdef.view.frustum + i;
6998 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7002 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7006 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7010 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7014 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7018 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7022 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7026 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7034 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7038 for (i = 0;i < numplanes;i++)
7045 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7049 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7053 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7057 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7061 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7065 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7069 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7073 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7081 //==================================================================================
7083 // LordHavoc: this stores temporary data used within the same frame
7085 typedef struct r_framedata_mem_s
7087 struct r_framedata_mem_s *purge; // older mem block to free on next frame
7088 size_t size; // how much usable space
7089 size_t current; // how much space in use
7090 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
7091 size_t wantedsize; // how much space was allocated
7092 unsigned char *data; // start of real data (16byte aligned)
7096 static r_framedata_mem_t *r_framedata_mem;
7098 void R_FrameData_Reset(void)
7100 while (r_framedata_mem)
7102 r_framedata_mem_t *next = r_framedata_mem->purge;
7103 Mem_Free(r_framedata_mem);
7104 r_framedata_mem = next;
7108 void R_FrameData_Resize(void)
7111 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7112 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
7113 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
7115 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
7116 newmem->wantedsize = wantedsize;
7117 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
7118 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
7119 newmem->current = 0;
7121 newmem->purge = r_framedata_mem;
7122 r_framedata_mem = newmem;
7126 void R_FrameData_NewFrame(void)
7128 R_FrameData_Resize();
7129 if (!r_framedata_mem)
7131 // if we ran out of space on the last frame, free the old memory now
7132 while (r_framedata_mem->purge)
7134 // repeatedly remove the second item in the list, leaving only head
7135 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
7136 Mem_Free(r_framedata_mem->purge);
7137 r_framedata_mem->purge = next;
7139 // reset the current mem pointer
7140 r_framedata_mem->current = 0;
7141 r_framedata_mem->mark = 0;
7144 void *R_FrameData_Alloc(size_t size)
7148 // align to 16 byte boundary - the data pointer is already aligned, so we
7149 // only need to ensure the size of every allocation is also aligned
7150 size = (size + 15) & ~15;
7152 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
7154 // emergency - we ran out of space, allocate more memory
7155 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
7156 R_FrameData_Resize();
7159 data = r_framedata_mem->data + r_framedata_mem->current;
7160 r_framedata_mem->current += size;
7162 // count the usage for stats
7163 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
7164 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
7166 return (void *)data;
7169 void *R_FrameData_Store(size_t size, void *data)
7171 void *d = R_FrameData_Alloc(size);
7173 memcpy(d, data, size);
7177 void R_FrameData_SetMark(void)
7179 if (!r_framedata_mem)
7181 r_framedata_mem->mark = r_framedata_mem->current;
7184 void R_FrameData_ReturnToMark(void)
7186 if (!r_framedata_mem)
7188 r_framedata_mem->current = r_framedata_mem->mark;
7191 //==================================================================================
7193 // LordHavoc: animcache originally written by Echon, rewritten since then
7196 * Animation cache prevents re-generating mesh data for an animated model
7197 * multiple times in one frame for lighting, shadowing, reflections, etc.
7200 void R_AnimCache_Free(void)
7204 void R_AnimCache_ClearCache(void)
7207 entity_render_t *ent;
7209 for (i = 0;i < r_refdef.scene.numentities;i++)
7211 ent = r_refdef.scene.entities[i];
7212 ent->animcache_vertex3f = NULL;
7213 ent->animcache_normal3f = NULL;
7214 ent->animcache_svector3f = NULL;
7215 ent->animcache_tvector3f = NULL;
7216 ent->animcache_vertexmesh = NULL;
7217 ent->animcache_vertex3fbuffer = NULL;
7218 ent->animcache_vertexmeshbuffer = NULL;
7222 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7226 // check if we need the meshbuffers
7227 if (!vid.useinterleavedarrays)
7230 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7231 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7232 // TODO: upload vertex3f buffer?
7233 if (ent->animcache_vertexmesh)
7235 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7236 for (i = 0;i < numvertices;i++)
7237 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7238 if (ent->animcache_svector3f)
7239 for (i = 0;i < numvertices;i++)
7240 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7241 if (ent->animcache_tvector3f)
7242 for (i = 0;i < numvertices;i++)
7243 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7244 if (ent->animcache_normal3f)
7245 for (i = 0;i < numvertices;i++)
7246 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7247 // TODO: upload vertexmeshbuffer?
7251 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7253 dp_model_t *model = ent->model;
7255 // see if it's already cached this frame
7256 if (ent->animcache_vertex3f)
7258 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7259 if (wantnormals || wanttangents)
7261 if (ent->animcache_normal3f)
7262 wantnormals = false;
7263 if (ent->animcache_svector3f)
7264 wanttangents = false;
7265 if (wantnormals || wanttangents)
7267 numvertices = model->surfmesh.num_vertices;
7269 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7272 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7273 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7275 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7276 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7282 // see if this ent is worth caching
7283 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7285 // get some memory for this entity and generate mesh data
7286 numvertices = model->surfmesh.num_vertices;
7287 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7289 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7292 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7293 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7295 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7296 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7301 void R_AnimCache_CacheVisibleEntities(void)
7304 qboolean wantnormals = true;
7305 qboolean wanttangents = !r_showsurfaces.integer;
7307 switch(vid.renderpath)
7309 case RENDERPATH_GL20:
7310 case RENDERPATH_D3D9:
7311 case RENDERPATH_D3D10:
7312 case RENDERPATH_D3D11:
7313 case RENDERPATH_GLES2:
7315 case RENDERPATH_GL13:
7316 case RENDERPATH_GL11:
7317 wanttangents = false;
7319 case RENDERPATH_SOFT:
7323 if (r_shownormals.integer)
7324 wanttangents = wantnormals = true;
7326 // TODO: thread this
7327 // NOTE: R_PrepareRTLights() also caches entities
7329 for (i = 0;i < r_refdef.scene.numentities;i++)
7330 if (r_refdef.viewcache.entityvisible[i])
7331 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7334 //==================================================================================
7336 static void R_View_UpdateEntityLighting (void)
7339 entity_render_t *ent;
7340 vec3_t tempdiffusenormal, avg;
7341 vec_t f, fa, fd, fdd;
7342 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7344 for (i = 0;i < r_refdef.scene.numentities;i++)
7346 ent = r_refdef.scene.entities[i];
7348 // skip unseen models
7349 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7353 if (ent->model && ent->model->brush.num_leafs)
7355 // TODO: use modellight for r_ambient settings on world?
7356 VectorSet(ent->modellight_ambient, 0, 0, 0);
7357 VectorSet(ent->modellight_diffuse, 0, 0, 0);
7358 VectorSet(ent->modellight_lightdir, 0, 0, 1);
7362 // fetch the lighting from the worldmodel data
7363 VectorClear(ent->modellight_ambient);
7364 VectorClear(ent->modellight_diffuse);
7365 VectorClear(tempdiffusenormal);
7366 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7369 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7371 // complete lightning for lit sprites
7372 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
7373 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
7375 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
7376 org[2] = org[2] + r_overheadsprites_pushback.value;
7377 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
7380 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
7382 if(ent->flags & RENDER_EQUALIZE)
7384 // first fix up ambient lighting...
7385 if(r_equalize_entities_minambient.value > 0)
7387 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7390 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7391 if(fa < r_equalize_entities_minambient.value * fd)
7394 // fa'/fd' = minambient
7395 // fa'+0.25*fd' = fa+0.25*fd
7397 // fa' = fd' * minambient
7398 // fd'*(0.25+minambient) = fa+0.25*fd
7400 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7401 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7403 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7404 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
7405 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7406 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7411 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7413 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
7414 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7418 // adjust brightness and saturation to target
7419 avg[0] = avg[1] = avg[2] = fa / f;
7420 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
7421 avg[0] = avg[1] = avg[2] = fd / f;
7422 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
7428 VectorSet(ent->modellight_ambient, 1, 1, 1);
7430 // move the light direction into modelspace coordinates for lighting code
7431 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7432 if(VectorLength2(ent->modellight_lightdir) == 0)
7433 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7434 VectorNormalize(ent->modellight_lightdir);
7438 #define MAX_LINEOFSIGHTTRACES 64
7440 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7443 vec3_t boxmins, boxmaxs;
7446 dp_model_t *model = r_refdef.scene.worldmodel;
7448 if (!model || !model->brush.TraceLineOfSight)
7451 // expand the box a little
7452 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7453 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7454 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7455 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7456 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7457 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7459 // return true if eye is inside enlarged box
7460 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7464 VectorCopy(eye, start);
7465 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7466 if (model->brush.TraceLineOfSight(model, start, end))
7469 // try various random positions
7470 for (i = 0;i < numsamples;i++)
7472 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7473 if (model->brush.TraceLineOfSight(model, start, end))
7481 static void R_View_UpdateEntityVisible (void)
7486 entity_render_t *ent;
7488 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7489 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7490 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
7491 : RENDER_EXTERIORMODEL;
7492 if (!r_drawviewmodel.integer)
7493 renderimask |= RENDER_VIEWMODEL;
7494 if (!r_drawexteriormodel.integer)
7495 renderimask |= RENDER_EXTERIORMODEL;
7496 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
7498 // worldmodel can check visibility
7499 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
7500 for (i = 0;i < r_refdef.scene.numentities;i++)
7502 ent = r_refdef.scene.entities[i];
7503 if (!(ent->flags & renderimask))
7504 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)))
7505 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))
7506 r_refdef.viewcache.entityvisible[i] = true;
7508 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
7509 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
7511 for (i = 0;i < r_refdef.scene.numentities;i++)
7513 ent = r_refdef.scene.entities[i];
7514 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
7516 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
7518 continue; // temp entities do pvs only
7519 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
7520 ent->last_trace_visibility = realtime;
7521 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
7522 r_refdef.viewcache.entityvisible[i] = 0;
7529 // no worldmodel or it can't check visibility
7530 for (i = 0;i < r_refdef.scene.numentities;i++)
7532 ent = r_refdef.scene.entities[i];
7533 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));
7538 /// only used if skyrendermasked, and normally returns false
7539 int R_DrawBrushModelsSky (void)
7542 entity_render_t *ent;
7545 for (i = 0;i < r_refdef.scene.numentities;i++)
7547 if (!r_refdef.viewcache.entityvisible[i])
7549 ent = r_refdef.scene.entities[i];
7550 if (!ent->model || !ent->model->DrawSky)
7552 ent->model->DrawSky(ent);
7558 static void R_DrawNoModel(entity_render_t *ent);
7559 static void R_DrawModels(void)
7562 entity_render_t *ent;
7564 for (i = 0;i < r_refdef.scene.numentities;i++)
7566 if (!r_refdef.viewcache.entityvisible[i])
7568 ent = r_refdef.scene.entities[i];
7569 r_refdef.stats.entities++;
7570 if (ent->model && ent->model->Draw != NULL)
7571 ent->model->Draw(ent);
7577 static void R_DrawModelsDepth(void)
7580 entity_render_t *ent;
7582 for (i = 0;i < r_refdef.scene.numentities;i++)
7584 if (!r_refdef.viewcache.entityvisible[i])
7586 ent = r_refdef.scene.entities[i];
7587 if (ent->model && ent->model->DrawDepth != NULL)
7588 ent->model->DrawDepth(ent);
7592 static void R_DrawModelsDebug(void)
7595 entity_render_t *ent;
7597 for (i = 0;i < r_refdef.scene.numentities;i++)
7599 if (!r_refdef.viewcache.entityvisible[i])
7601 ent = r_refdef.scene.entities[i];
7602 if (ent->model && ent->model->DrawDebug != NULL)
7603 ent->model->DrawDebug(ent);
7607 static void R_DrawModelsAddWaterPlanes(void)
7610 entity_render_t *ent;
7612 for (i = 0;i < r_refdef.scene.numentities;i++)
7614 if (!r_refdef.viewcache.entityvisible[i])
7616 ent = r_refdef.scene.entities[i];
7617 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
7618 ent->model->DrawAddWaterPlanes(ent);
7622 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
7624 if (r_hdr_irisadaptation.integer)
7628 vec3_t diffusenormal;
7633 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
7634 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
7635 brightness = max(0.0000001f, brightness);
7636 goal = r_hdr_irisadaptation_multiplier.value / brightness;
7637 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
7638 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
7639 current = r_hdr_irisadaptation_value.value;
7641 current = min(current + adjust, goal);
7642 else if (current > goal)
7643 current = max(current - adjust, goal);
7644 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
7645 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
7647 else if (r_hdr_irisadaptation_value.value != 1.0f)
7648 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
7651 static void R_View_SetFrustum(const int *scissor)
7654 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
7655 vec3_t forward, left, up, origin, v;
7659 // flipped x coordinates (because x points left here)
7660 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
7661 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
7663 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
7664 switch(vid.renderpath)
7666 case RENDERPATH_D3D9:
7667 case RENDERPATH_D3D10:
7668 case RENDERPATH_D3D11:
7669 case RENDERPATH_SOFT:
7670 // non-flipped y coordinates
7671 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7672 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7674 case RENDERPATH_GL11:
7675 case RENDERPATH_GL13:
7676 case RENDERPATH_GL20:
7677 case RENDERPATH_GLES2:
7678 // non-flipped y coordinates
7679 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7680 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7685 // we can't trust r_refdef.view.forward and friends in reflected scenes
7686 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
7689 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
7690 r_refdef.view.frustum[0].normal[1] = 0 - 0;
7691 r_refdef.view.frustum[0].normal[2] = -1 - 0;
7692 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
7693 r_refdef.view.frustum[1].normal[1] = 0 + 0;
7694 r_refdef.view.frustum[1].normal[2] = -1 + 0;
7695 r_refdef.view.frustum[2].normal[0] = 0 - 0;
7696 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
7697 r_refdef.view.frustum[2].normal[2] = -1 - 0;
7698 r_refdef.view.frustum[3].normal[0] = 0 + 0;
7699 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
7700 r_refdef.view.frustum[3].normal[2] = -1 + 0;
7704 zNear = r_refdef.nearclip;
7705 nudge = 1.0 - 1.0 / (1<<23);
7706 r_refdef.view.frustum[4].normal[0] = 0 - 0;
7707 r_refdef.view.frustum[4].normal[1] = 0 - 0;
7708 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7709 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
7710 r_refdef.view.frustum[5].normal[0] = 0 + 0;
7711 r_refdef.view.frustum[5].normal[1] = 0 + 0;
7712 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7713 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7719 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
7720 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
7721 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
7722 r_refdef.view.frustum[0].dist = m[15] - m[12];
7724 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
7725 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
7726 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
7727 r_refdef.view.frustum[1].dist = m[15] + m[12];
7729 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
7730 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
7731 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
7732 r_refdef.view.frustum[2].dist = m[15] - m[13];
7734 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
7735 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
7736 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
7737 r_refdef.view.frustum[3].dist = m[15] + m[13];
7739 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
7740 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
7741 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
7742 r_refdef.view.frustum[4].dist = m[15] - m[14];
7744 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
7745 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
7746 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
7747 r_refdef.view.frustum[5].dist = m[15] + m[14];
7750 if (r_refdef.view.useperspective)
7752 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
7753 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]);
7754 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]);
7755 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]);
7756 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]);
7758 // then the normals from the corners relative to origin
7759 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
7760 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
7761 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
7762 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
7764 // in a NORMAL view, forward cross left == up
7765 // in a REFLECTED view, forward cross left == down
7766 // so our cross products above need to be adjusted for a left handed coordinate system
7767 CrossProduct(forward, left, v);
7768 if(DotProduct(v, up) < 0)
7770 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
7771 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
7772 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
7773 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
7776 // Leaving those out was a mistake, those were in the old code, and they
7777 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
7778 // I couldn't reproduce it after adding those normalizations. --blub
7779 VectorNormalize(r_refdef.view.frustum[0].normal);
7780 VectorNormalize(r_refdef.view.frustum[1].normal);
7781 VectorNormalize(r_refdef.view.frustum[2].normal);
7782 VectorNormalize(r_refdef.view.frustum[3].normal);
7784 // make the corners absolute
7785 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
7786 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
7787 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
7788 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
7791 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7793 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
7794 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
7795 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
7796 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
7797 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7801 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
7802 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
7803 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
7804 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
7805 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7806 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
7807 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
7808 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
7809 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
7810 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7812 r_refdef.view.numfrustumplanes = 5;
7814 if (r_refdef.view.useclipplane)
7816 r_refdef.view.numfrustumplanes = 6;
7817 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
7820 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7821 PlaneClassify(r_refdef.view.frustum + i);
7823 // LordHavoc: note to all quake engine coders, Quake had a special case
7824 // for 90 degrees which assumed a square view (wrong), so I removed it,
7825 // Quake2 has it disabled as well.
7827 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
7828 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
7829 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
7830 //PlaneClassify(&frustum[0]);
7832 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
7833 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
7834 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
7835 //PlaneClassify(&frustum[1]);
7837 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
7838 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
7839 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
7840 //PlaneClassify(&frustum[2]);
7842 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
7843 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
7844 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
7845 //PlaneClassify(&frustum[3]);
7848 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
7849 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
7850 //PlaneClassify(&frustum[4]);
7853 void R_View_UpdateWithScissor(const int *myscissor)
7855 R_Main_ResizeViewCache();
7856 R_View_SetFrustum(myscissor);
7857 R_View_WorldVisibility(r_refdef.view.useclipplane);
7858 R_View_UpdateEntityVisible();
7859 R_View_UpdateEntityLighting();
7862 void R_View_Update(void)
7864 R_Main_ResizeViewCache();
7865 R_View_SetFrustum(NULL);
7866 R_View_WorldVisibility(r_refdef.view.useclipplane);
7867 R_View_UpdateEntityVisible();
7868 R_View_UpdateEntityLighting();
7871 void R_SetupView(qboolean allowwaterclippingplane)
7873 const float *customclipplane = NULL;
7875 if (r_refdef.view.useclipplane && allowwaterclippingplane)
7877 // LordHavoc: couldn't figure out how to make this approach the
7878 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
7879 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
7880 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
7881 dist = r_refdef.view.clipplane.dist;
7882 plane[0] = r_refdef.view.clipplane.normal[0];
7883 plane[1] = r_refdef.view.clipplane.normal[1];
7884 plane[2] = r_refdef.view.clipplane.normal[2];
7886 customclipplane = plane;
7889 if (!r_refdef.view.useperspective)
7890 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);
7891 else if (vid.stencil && r_useinfinitefarclip.integer)
7892 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);
7894 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);
7895 R_SetViewport(&r_refdef.view.viewport);
7898 void R_EntityMatrix(const matrix4x4_t *matrix)
7900 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
7902 gl_modelmatrixchanged = false;
7903 gl_modelmatrix = *matrix;
7904 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
7905 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
7906 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
7907 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
7909 switch(vid.renderpath)
7911 case RENDERPATH_D3D9:
7913 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
7914 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
7917 case RENDERPATH_D3D10:
7918 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
7920 case RENDERPATH_D3D11:
7921 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
7923 case RENDERPATH_GL13:
7924 case RENDERPATH_GL11:
7925 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7927 case RENDERPATH_SOFT:
7928 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
7929 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
7931 case RENDERPATH_GL20:
7932 case RENDERPATH_GLES2:
7933 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
7934 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
7940 void R_ResetViewRendering2D(void)
7942 r_viewport_t viewport;
7945 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
7946 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);
7947 R_SetViewport(&viewport);
7948 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
7949 GL_Color(1, 1, 1, 1);
7950 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7951 GL_BlendFunc(GL_ONE, GL_ZERO);
7952 GL_ScissorTest(false);
7953 GL_DepthMask(false);
7954 GL_DepthRange(0, 1);
7955 GL_DepthTest(false);
7956 GL_DepthFunc(GL_LEQUAL);
7957 R_EntityMatrix(&identitymatrix);
7958 R_Mesh_ResetTextureState();
7959 GL_PolygonOffset(0, 0);
7960 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
7961 switch(vid.renderpath)
7963 case RENDERPATH_GL11:
7964 case RENDERPATH_GL13:
7965 case RENDERPATH_GL20:
7966 case RENDERPATH_GLES2:
7967 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7969 case RENDERPATH_D3D9:
7970 case RENDERPATH_D3D10:
7971 case RENDERPATH_D3D11:
7972 case RENDERPATH_SOFT:
7975 GL_CullFace(GL_NONE);
7978 void R_ResetViewRendering3D(void)
7983 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7984 GL_Color(1, 1, 1, 1);
7985 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7986 GL_BlendFunc(GL_ONE, GL_ZERO);
7987 GL_ScissorTest(true);
7989 GL_DepthRange(0, 1);
7991 GL_DepthFunc(GL_LEQUAL);
7992 R_EntityMatrix(&identitymatrix);
7993 R_Mesh_ResetTextureState();
7994 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7995 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
7996 switch(vid.renderpath)
7998 case RENDERPATH_GL11:
7999 case RENDERPATH_GL13:
8000 case RENDERPATH_GL20:
8001 case RENDERPATH_GLES2:
8002 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8004 case RENDERPATH_D3D9:
8005 case RENDERPATH_D3D10:
8006 case RENDERPATH_D3D11:
8007 case RENDERPATH_SOFT:
8010 GL_CullFace(r_refdef.view.cullface_back);
8015 R_RenderView_UpdateViewVectors
8018 static void R_RenderView_UpdateViewVectors(void)
8020 // break apart the view matrix into vectors for various purposes
8021 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8022 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8023 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8024 VectorNegate(r_refdef.view.left, r_refdef.view.right);
8025 // make an inverted copy of the view matrix for tracking sprites
8026 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8029 void R_RenderScene(void);
8030 void R_RenderWaterPlanes(void);
8032 static void R_Water_StartFrame(void)
8035 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8036 r_waterstate_waterplane_t *p;
8038 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8041 switch(vid.renderpath)
8043 case RENDERPATH_GL20:
8044 case RENDERPATH_D3D9:
8045 case RENDERPATH_D3D10:
8046 case RENDERPATH_D3D11:
8047 case RENDERPATH_SOFT:
8048 case RENDERPATH_GLES2:
8050 case RENDERPATH_GL13:
8051 case RENDERPATH_GL11:
8055 // set waterwidth and waterheight to the water resolution that will be
8056 // used (often less than the screen resolution for faster rendering)
8057 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8058 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8060 // calculate desired texture sizes
8061 // can't use water if the card does not support the texture size
8062 if (!r_water.integer || r_showsurfaces.integer)
8063 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8064 else if (vid.support.arb_texture_non_power_of_two)
8066 texturewidth = waterwidth;
8067 textureheight = waterheight;
8068 camerawidth = waterwidth;
8069 cameraheight = waterheight;
8073 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
8074 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
8075 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
8076 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
8079 // allocate textures as needed
8080 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8082 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8083 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8085 if (p->texture_refraction)
8086 R_FreeTexture(p->texture_refraction);
8087 p->texture_refraction = NULL;
8088 if (p->texture_reflection)
8089 R_FreeTexture(p->texture_reflection);
8090 p->texture_reflection = NULL;
8091 if (p->texture_camera)
8092 R_FreeTexture(p->texture_camera);
8093 p->texture_camera = NULL;
8095 memset(&r_waterstate, 0, sizeof(r_waterstate));
8096 r_waterstate.texturewidth = texturewidth;
8097 r_waterstate.textureheight = textureheight;
8098 r_waterstate.camerawidth = camerawidth;
8099 r_waterstate.cameraheight = cameraheight;
8102 if (r_waterstate.texturewidth)
8104 r_waterstate.enabled = true;
8106 // when doing a reduced render (HDR) we want to use a smaller area
8107 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8108 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8110 // set up variables that will be used in shader setup
8111 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8112 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8113 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8114 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8117 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8118 r_waterstate.numwaterplanes = 0;
8121 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8123 int triangleindex, planeindex;
8129 r_waterstate_waterplane_t *p;
8130 texture_t *t = R_GetCurrentTexture(surface->texture);
8132 // just use the first triangle with a valid normal for any decisions
8133 VectorClear(normal);
8134 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8136 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8137 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8138 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8139 TriangleNormal(vert[0], vert[1], vert[2], normal);
8140 if (VectorLength2(normal) >= 0.001)
8144 VectorCopy(normal, plane.normal);
8145 VectorNormalize(plane.normal);
8146 plane.dist = DotProduct(vert[0], plane.normal);
8147 PlaneClassify(&plane);
8148 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8150 // skip backfaces (except if nocullface is set)
8151 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8153 VectorNegate(plane.normal, plane.normal);
8155 PlaneClassify(&plane);
8159 // find a matching plane if there is one
8160 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8161 if(p->camera_entity == t->camera_entity)
8162 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8164 if (planeindex >= r_waterstate.maxwaterplanes)
8165 return; // nothing we can do, out of planes
8167 // if this triangle does not fit any known plane rendered this frame, add one
8168 if (planeindex >= r_waterstate.numwaterplanes)
8170 // store the new plane
8171 r_waterstate.numwaterplanes++;
8173 // clear materialflags and pvs
8174 p->materialflags = 0;
8175 p->pvsvalid = false;
8176 p->camera_entity = t->camera_entity;
8177 VectorCopy(surface->mins, p->mins);
8178 VectorCopy(surface->maxs, p->maxs);
8183 p->mins[0] = min(p->mins[0], surface->mins[0]);
8184 p->mins[1] = min(p->mins[1], surface->mins[1]);
8185 p->mins[2] = min(p->mins[2], surface->mins[2]);
8186 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8187 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8188 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8190 // merge this surface's materialflags into the waterplane
8191 p->materialflags |= t->currentmaterialflags;
8192 if(!(p->materialflags & MATERIALFLAG_CAMERA))
8194 // merge this surface's PVS into the waterplane
8195 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8196 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8197 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8199 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8205 static void R_Water_ProcessPlanes(void)
8208 r_refdef_view_t originalview;
8209 r_refdef_view_t myview;
8211 r_waterstate_waterplane_t *p;
8214 originalview = r_refdef.view;
8216 // make sure enough textures are allocated
8217 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8219 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8221 if (!p->texture_refraction)
8222 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);
8223 if (!p->texture_refraction)
8226 else if (p->materialflags & MATERIALFLAG_CAMERA)
8228 if (!p->texture_camera)
8229 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);
8230 if (!p->texture_camera)
8234 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8236 if (!p->texture_reflection)
8237 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);
8238 if (!p->texture_reflection)
8244 r_refdef.view = originalview;
8245 r_refdef.view.showdebug = false;
8246 r_refdef.view.width = r_waterstate.waterwidth;
8247 r_refdef.view.height = r_waterstate.waterheight;
8248 r_refdef.view.useclipplane = true;
8249 myview = r_refdef.view;
8250 r_waterstate.renderingscene = true;
8251 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8253 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8255 r_refdef.view = myview;
8256 if(r_water_scissormode.integer)
8259 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8260 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8263 // render reflected scene and copy into texture
8264 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8265 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8266 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8267 r_refdef.view.clipplane = p->plane;
8269 // reverse the cullface settings for this render
8270 r_refdef.view.cullface_front = GL_FRONT;
8271 r_refdef.view.cullface_back = GL_BACK;
8272 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8274 r_refdef.view.usecustompvs = true;
8276 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8278 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8281 R_ResetViewRendering3D();
8282 R_ClearScreen(r_refdef.fogenabled);
8283 if(r_water_scissormode.integer & 2)
8284 R_View_UpdateWithScissor(myscissor);
8287 if(r_water_scissormode.integer & 1)
8288 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8291 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);
8294 // render the normal view scene and copy into texture
8295 // (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)
8296 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8298 r_refdef.view = myview;
8299 if(r_water_scissormode.integer)
8302 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8303 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8306 r_waterstate.renderingrefraction = true;
8308 r_refdef.view.clipplane = p->plane;
8309 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8310 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8312 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8314 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8315 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8316 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8317 R_RenderView_UpdateViewVectors();
8318 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8320 r_refdef.view.usecustompvs = true;
8321 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);
8325 PlaneClassify(&r_refdef.view.clipplane);
8327 R_ResetViewRendering3D();
8328 R_ClearScreen(r_refdef.fogenabled);
8329 if(r_water_scissormode.integer & 2)
8330 R_View_UpdateWithScissor(myscissor);
8333 if(r_water_scissormode.integer & 1)
8334 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8337 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);
8338 r_waterstate.renderingrefraction = false;
8340 else if (p->materialflags & MATERIALFLAG_CAMERA)
8342 r_refdef.view = myview;
8344 r_refdef.view.clipplane = p->plane;
8345 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8346 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8348 r_refdef.view.width = r_waterstate.camerawidth;
8349 r_refdef.view.height = r_waterstate.cameraheight;
8350 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8351 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8353 if(p->camera_entity)
8355 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8356 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8359 // note: all of the view is used for displaying... so
8360 // there is no use in scissoring
8362 // reverse the cullface settings for this render
8363 r_refdef.view.cullface_front = GL_FRONT;
8364 r_refdef.view.cullface_back = GL_BACK;
8365 // also reverse the view matrix
8366 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
8367 R_RenderView_UpdateViewVectors();
8368 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8370 r_refdef.view.usecustompvs = true;
8371 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);
8374 // camera needs no clipplane
8375 r_refdef.view.useclipplane = false;
8377 PlaneClassify(&r_refdef.view.clipplane);
8379 R_ResetViewRendering3D();
8380 R_ClearScreen(r_refdef.fogenabled);
8384 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);
8385 r_waterstate.renderingrefraction = false;
8389 r_waterstate.renderingscene = false;
8390 r_refdef.view = originalview;
8391 R_ResetViewRendering3D();
8392 R_ClearScreen(r_refdef.fogenabled);
8396 r_refdef.view = originalview;
8397 r_waterstate.renderingscene = false;
8398 Cvar_SetValueQuick(&r_water, 0);
8399 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
8403 void R_Bloom_StartFrame(void)
8405 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8407 switch(vid.renderpath)
8409 case RENDERPATH_GL20:
8410 case RENDERPATH_D3D9:
8411 case RENDERPATH_D3D10:
8412 case RENDERPATH_D3D11:
8413 case RENDERPATH_SOFT:
8414 case RENDERPATH_GLES2:
8416 case RENDERPATH_GL13:
8417 case RENDERPATH_GL11:
8421 // set bloomwidth and bloomheight to the bloom resolution that will be
8422 // used (often less than the screen resolution for faster rendering)
8423 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8424 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8425 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8426 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8427 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8429 // calculate desired texture sizes
8430 if (vid.support.arb_texture_non_power_of_two)
8432 screentexturewidth = r_refdef.view.width;
8433 screentextureheight = r_refdef.view.height;
8434 bloomtexturewidth = r_bloomstate.bloomwidth;
8435 bloomtextureheight = r_bloomstate.bloomheight;
8439 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
8440 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
8441 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
8442 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
8445 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))
8447 Cvar_SetValueQuick(&r_hdr, 0);
8448 Cvar_SetValueQuick(&r_bloom, 0);
8449 Cvar_SetValueQuick(&r_motionblur, 0);
8450 Cvar_SetValueQuick(&r_damageblur, 0);
8453 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)))
8454 screentexturewidth = screentextureheight = 0;
8455 if (!r_hdr.integer && !r_bloom.integer)
8456 bloomtexturewidth = bloomtextureheight = 0;
8458 // allocate textures as needed
8459 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8461 if (r_bloomstate.texture_screen)
8462 R_FreeTexture(r_bloomstate.texture_screen);
8463 r_bloomstate.texture_screen = NULL;
8464 r_bloomstate.screentexturewidth = screentexturewidth;
8465 r_bloomstate.screentextureheight = screentextureheight;
8466 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8467 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);
8469 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8471 if (r_bloomstate.texture_bloom)
8472 R_FreeTexture(r_bloomstate.texture_bloom);
8473 r_bloomstate.texture_bloom = NULL;
8474 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8475 r_bloomstate.bloomtextureheight = bloomtextureheight;
8476 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8477 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);
8480 // when doing a reduced render (HDR) we want to use a smaller area
8481 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8482 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8483 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8484 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8485 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8487 // set up a texcoord array for the full resolution screen image
8488 // (we have to keep this around to copy back during final render)
8489 r_bloomstate.screentexcoord2f[0] = 0;
8490 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
8491 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
8492 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
8493 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
8494 r_bloomstate.screentexcoord2f[5] = 0;
8495 r_bloomstate.screentexcoord2f[6] = 0;
8496 r_bloomstate.screentexcoord2f[7] = 0;
8498 // set up a texcoord array for the reduced resolution bloom image
8499 // (which will be additive blended over the screen image)
8500 r_bloomstate.bloomtexcoord2f[0] = 0;
8501 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8502 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8503 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8504 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8505 r_bloomstate.bloomtexcoord2f[5] = 0;
8506 r_bloomstate.bloomtexcoord2f[6] = 0;
8507 r_bloomstate.bloomtexcoord2f[7] = 0;
8509 switch(vid.renderpath)
8511 case RENDERPATH_GL11:
8512 case RENDERPATH_GL13:
8513 case RENDERPATH_GL20:
8514 case RENDERPATH_SOFT:
8515 case RENDERPATH_GLES2:
8517 case RENDERPATH_D3D9:
8518 case RENDERPATH_D3D10:
8519 case RENDERPATH_D3D11:
8522 for (i = 0;i < 4;i++)
8524 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
8525 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
8526 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
8527 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
8533 if (r_hdr.integer || r_bloom.integer)
8535 r_bloomstate.enabled = true;
8536 r_bloomstate.hdr = r_hdr.integer != 0;
8539 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);
8542 void R_Bloom_CopyBloomTexture(float colorscale)
8544 r_refdef.stats.bloom++;
8546 // scale down screen texture to the bloom texture size
8548 R_SetViewport(&r_bloomstate.viewport);
8549 GL_BlendFunc(GL_ONE, GL_ZERO);
8550 GL_Color(colorscale, colorscale, colorscale, 1);
8551 // 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...
8552 switch(vid.renderpath)
8554 case RENDERPATH_GL11:
8555 case RENDERPATH_GL13:
8556 case RENDERPATH_GL20:
8557 case RENDERPATH_SOFT:
8558 case RENDERPATH_GLES2:
8559 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8561 case RENDERPATH_D3D9:
8562 case RENDERPATH_D3D10:
8563 case RENDERPATH_D3D11:
8564 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8567 // TODO: do boxfilter scale-down in shader?
8568 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8569 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8570 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8572 // we now have a bloom image in the framebuffer
8573 // copy it into the bloom image texture for later processing
8574 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);
8575 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8578 void R_Bloom_CopyHDRTexture(void)
8580 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);
8581 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8584 void R_Bloom_MakeTexture(void)
8587 float xoffset, yoffset, r, brighten;
8589 r_refdef.stats.bloom++;
8591 R_ResetViewRendering2D();
8593 // we have a bloom image in the framebuffer
8595 R_SetViewport(&r_bloomstate.viewport);
8597 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
8600 r = bound(0, r_bloom_colorexponent.value / x, 1);
8601 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
8603 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
8604 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8605 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8606 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8608 // copy the vertically blurred bloom view to a texture
8609 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);
8610 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8613 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
8614 brighten = r_bloom_brighten.value;
8616 brighten *= r_hdr_range.value;
8617 brighten = sqrt(brighten);
8619 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
8620 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8622 for (dir = 0;dir < 2;dir++)
8624 // blend on at multiple vertical offsets to achieve a vertical blur
8625 // TODO: do offset blends using GLSL
8626 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
8627 GL_BlendFunc(GL_ONE, GL_ZERO);
8628 for (x = -range;x <= range;x++)
8630 if (!dir){xoffset = 0;yoffset = x;}
8631 else {xoffset = x;yoffset = 0;}
8632 xoffset /= (float)r_bloomstate.bloomtexturewidth;
8633 yoffset /= (float)r_bloomstate.bloomtextureheight;
8634 // compute a texcoord array with the specified x and y offset
8635 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
8636 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8637 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8638 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8639 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8640 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
8641 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
8642 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
8643 // this r value looks like a 'dot' particle, fading sharply to
8644 // black at the edges
8645 // (probably not realistic but looks good enough)
8646 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
8647 //r = brighten/(range*2+1);
8648 r = brighten / (range * 2 + 1);
8650 r *= (1 - x*x/(float)(range*range));
8651 GL_Color(r, r, r, 1);
8652 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
8653 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8654 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8655 GL_BlendFunc(GL_ONE, GL_ONE);
8658 // copy the vertically blurred bloom view to a texture
8659 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);
8660 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8664 void R_HDR_RenderBloomTexture(void)
8666 int oldwidth, oldheight;
8667 float oldcolorscale;
8668 qboolean oldwaterstate;
8670 oldwaterstate = r_waterstate.enabled;
8671 oldcolorscale = r_refdef.view.colorscale;
8672 oldwidth = r_refdef.view.width;
8673 oldheight = r_refdef.view.height;
8674 r_refdef.view.width = r_bloomstate.bloomwidth;
8675 r_refdef.view.height = r_bloomstate.bloomheight;
8677 if(r_hdr.integer < 2)
8678 r_waterstate.enabled = false;
8680 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
8681 // TODO: add exposure compensation features
8682 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
8684 r_refdef.view.showdebug = false;
8685 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
8687 R_ResetViewRendering3D();
8689 R_ClearScreen(r_refdef.fogenabled);
8690 if (r_timereport_active)
8691 R_TimeReport("HDRclear");
8694 if (r_timereport_active)
8695 R_TimeReport("visibility");
8697 // only do secondary renders with HDR if r_hdr is 2 or higher
8698 r_waterstate.numwaterplanes = 0;
8699 if (r_waterstate.enabled)
8700 R_RenderWaterPlanes();
8702 r_refdef.view.showdebug = true;
8704 r_waterstate.numwaterplanes = 0;
8706 R_ResetViewRendering2D();
8708 R_Bloom_CopyHDRTexture();
8709 R_Bloom_MakeTexture();
8711 // restore the view settings
8712 r_waterstate.enabled = oldwaterstate;
8713 r_refdef.view.width = oldwidth;
8714 r_refdef.view.height = oldheight;
8715 r_refdef.view.colorscale = oldcolorscale;
8717 R_ResetViewRendering3D();
8719 R_ClearScreen(r_refdef.fogenabled);
8720 if (r_timereport_active)
8721 R_TimeReport("viewclear");
8724 static void R_BlendView(void)
8726 unsigned int permutation;
8727 float uservecs[4][4];
8729 switch (vid.renderpath)
8731 case RENDERPATH_GL20:
8732 case RENDERPATH_D3D9:
8733 case RENDERPATH_D3D10:
8734 case RENDERPATH_D3D11:
8735 case RENDERPATH_SOFT:
8736 case RENDERPATH_GLES2:
8738 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
8739 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
8740 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
8741 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
8742 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
8744 if (r_bloomstate.texture_screen)
8746 // make sure the buffer is available
8747 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
8749 R_ResetViewRendering2D();
8751 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
8753 // declare variables
8755 static float avgspeed;
8757 speed = VectorLength(cl.movement_velocity);
8759 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
8760 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
8762 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
8763 speed = bound(0, speed, 1);
8764 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
8766 // calculate values into a standard alpha
8767 cl.motionbluralpha = 1 - exp(-
8769 (r_motionblur.value * speed / 80)
8771 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
8774 max(0.0001, cl.time - cl.oldtime) // fps independent
8777 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
8778 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
8780 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
8782 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8783 GL_Color(1, 1, 1, cl.motionbluralpha);
8784 switch(vid.renderpath)
8786 case RENDERPATH_GL11:
8787 case RENDERPATH_GL13:
8788 case RENDERPATH_GL20:
8789 case RENDERPATH_SOFT:
8790 case RENDERPATH_GLES2:
8791 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8793 case RENDERPATH_D3D9:
8794 case RENDERPATH_D3D10:
8795 case RENDERPATH_D3D11:
8796 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8799 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8800 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8801 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8805 // copy view into the screen texture
8806 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);
8807 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8809 else if (!r_bloomstate.texture_bloom)
8811 // we may still have to do view tint...
8812 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8814 // apply a color tint to the whole view
8815 R_ResetViewRendering2D();
8816 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8817 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
8818 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8819 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8820 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8822 break; // no screen processing, no bloom, skip it
8825 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
8827 // render simple bloom effect
8828 // copy the screen and shrink it and darken it for the bloom process
8829 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
8830 // make the bloom texture
8831 R_Bloom_MakeTexture();
8834 #if _MSC_VER >= 1400
8835 #define sscanf sscanf_s
8837 memset(uservecs, 0, sizeof(uservecs));
8838 if (r_glsl_postprocess_uservec1_enable.integer)
8839 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
8840 if (r_glsl_postprocess_uservec2_enable.integer)
8841 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
8842 if (r_glsl_postprocess_uservec3_enable.integer)
8843 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
8844 if (r_glsl_postprocess_uservec4_enable.integer)
8845 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
8847 R_ResetViewRendering2D();
8848 GL_Color(1, 1, 1, 1);
8849 GL_BlendFunc(GL_ONE, GL_ZERO);
8851 switch(vid.renderpath)
8853 case RENDERPATH_GL20:
8854 case RENDERPATH_GLES2:
8855 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8856 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
8857 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
8858 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
8859 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
8860 if (r_glsl_permutation->loc_ViewTintColor >= 0) qglUniform4f(r_glsl_permutation->loc_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8861 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8862 if (r_glsl_permutation->loc_UserVec1 >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
8863 if (r_glsl_permutation->loc_UserVec2 >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
8864 if (r_glsl_permutation->loc_UserVec3 >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
8865 if (r_glsl_permutation->loc_UserVec4 >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
8866 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
8867 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8868 if (r_glsl_permutation->loc_BloomColorSubtract >= 0) qglUniform4f(r_glsl_permutation->loc_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
8870 case RENDERPATH_D3D9:
8872 // 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...
8873 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8874 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
8875 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
8876 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
8877 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
8878 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8879 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8880 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
8881 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
8882 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
8883 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
8884 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
8885 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
8886 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
8889 case RENDERPATH_D3D10:
8890 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
8892 case RENDERPATH_D3D11:
8893 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
8895 case RENDERPATH_SOFT:
8896 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8897 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
8898 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
8899 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
8900 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
8901 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8902 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8903 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
8904 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
8905 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
8906 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
8907 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
8908 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8909 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
8914 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8915 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8917 case RENDERPATH_GL13:
8918 case RENDERPATH_GL11:
8919 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8921 // apply a color tint to the whole view
8922 R_ResetViewRendering2D();
8923 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8924 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
8925 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8926 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8927 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8933 matrix4x4_t r_waterscrollmatrix;
8935 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
8937 if (r_refdef.fog_density)
8939 r_refdef.fogcolor[0] = r_refdef.fog_red;
8940 r_refdef.fogcolor[1] = r_refdef.fog_green;
8941 r_refdef.fogcolor[2] = r_refdef.fog_blue;
8943 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
8944 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
8945 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
8946 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
8950 VectorCopy(r_refdef.fogcolor, fogvec);
8951 // color.rgb *= ContrastBoost * SceneBrightness;
8952 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
8953 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
8954 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
8955 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
8960 void R_UpdateVariables(void)
8964 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
8966 r_refdef.farclip = r_farclip_base.value;
8967 if (r_refdef.scene.worldmodel)
8968 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
8969 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
8971 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
8972 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
8973 r_refdef.polygonfactor = 0;
8974 r_refdef.polygonoffset = 0;
8975 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8976 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8978 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
8979 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
8980 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
8981 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
8982 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
8983 if (FAKELIGHT_ENABLED)
8985 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
8987 if (r_showsurfaces.integer)
8989 r_refdef.scene.rtworld = false;
8990 r_refdef.scene.rtworldshadows = false;
8991 r_refdef.scene.rtdlight = false;
8992 r_refdef.scene.rtdlightshadows = false;
8993 r_refdef.lightmapintensity = 0;
8996 if (gamemode == GAME_NEHAHRA)
8998 if (gl_fogenable.integer)
9000 r_refdef.oldgl_fogenable = true;
9001 r_refdef.fog_density = gl_fogdensity.value;
9002 r_refdef.fog_red = gl_fogred.value;
9003 r_refdef.fog_green = gl_foggreen.value;
9004 r_refdef.fog_blue = gl_fogblue.value;
9005 r_refdef.fog_alpha = 1;
9006 r_refdef.fog_start = 0;
9007 r_refdef.fog_end = gl_skyclip.value;
9008 r_refdef.fog_height = 1<<30;
9009 r_refdef.fog_fadedepth = 128;
9011 else if (r_refdef.oldgl_fogenable)
9013 r_refdef.oldgl_fogenable = false;
9014 r_refdef.fog_density = 0;
9015 r_refdef.fog_red = 0;
9016 r_refdef.fog_green = 0;
9017 r_refdef.fog_blue = 0;
9018 r_refdef.fog_alpha = 0;
9019 r_refdef.fog_start = 0;
9020 r_refdef.fog_end = 0;
9021 r_refdef.fog_height = 1<<30;
9022 r_refdef.fog_fadedepth = 128;
9026 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9027 r_refdef.fog_start = max(0, r_refdef.fog_start);
9028 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9030 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9032 if (r_refdef.fog_density && r_drawfog.integer)
9034 r_refdef.fogenabled = true;
9035 // this is the point where the fog reaches 0.9986 alpha, which we
9036 // consider a good enough cutoff point for the texture
9037 // (0.9986 * 256 == 255.6)
9038 if (r_fog_exp2.integer)
9039 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9041 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9042 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9043 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9044 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9045 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9046 R_BuildFogHeightTexture();
9047 // fog color was already set
9048 // update the fog texture
9049 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)
9050 R_BuildFogTexture();
9051 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9052 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9055 r_refdef.fogenabled = false;
9057 switch(vid.renderpath)
9059 case RENDERPATH_GL20:
9060 case RENDERPATH_D3D9:
9061 case RENDERPATH_D3D10:
9062 case RENDERPATH_D3D11:
9063 case RENDERPATH_SOFT:
9064 case RENDERPATH_GLES2:
9065 if(v_glslgamma.integer && !vid_gammatables_trivial)
9067 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9069 // build GLSL gamma texture
9070 #define RAMPWIDTH 256
9071 unsigned short ramp[RAMPWIDTH * 3];
9072 unsigned char rampbgr[RAMPWIDTH][4];
9075 r_texture_gammaramps_serial = vid_gammatables_serial;
9077 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9078 for(i = 0; i < RAMPWIDTH; ++i)
9080 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9081 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9082 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9085 if (r_texture_gammaramps)
9087 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
9091 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9097 // remove GLSL gamma texture
9100 case RENDERPATH_GL13:
9101 case RENDERPATH_GL11:
9106 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9107 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9113 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9114 if( scenetype != r_currentscenetype ) {
9115 // store the old scenetype
9116 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9117 r_currentscenetype = scenetype;
9118 // move in the new scene
9119 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9128 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9130 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9131 if( scenetype == r_currentscenetype ) {
9132 return &r_refdef.scene;
9134 return &r_scenes_store[ scenetype ];
9143 int dpsoftrast_test;
9144 void R_RenderView(void)
9146 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
9148 dpsoftrast_test = r_test.integer;
9150 if (r_timereport_active)
9151 R_TimeReport("start");
9152 r_textureframe++; // used only by R_GetCurrentTexture
9153 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9155 if(R_CompileShader_CheckStaticParms())
9158 if (!r_drawentities.integer)
9159 r_refdef.scene.numentities = 0;
9161 R_AnimCache_ClearCache();
9162 R_FrameData_NewFrame();
9164 /* adjust for stereo display */
9165 if(R_Stereo_Active())
9167 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);
9168 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
9171 if (r_refdef.view.isoverlay)
9173 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9174 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9175 R_TimeReport("depthclear");
9177 r_refdef.view.showdebug = false;
9179 r_waterstate.enabled = false;
9180 r_waterstate.numwaterplanes = 0;
9184 r_refdef.view.matrix = originalmatrix;
9190 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9192 r_refdef.view.matrix = originalmatrix;
9193 return; //Host_Error ("R_RenderView: NULL worldmodel");
9196 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
9198 R_RenderView_UpdateViewVectors();
9200 R_Shadow_UpdateWorldLightSelection();
9202 R_Bloom_StartFrame();
9203 R_Water_StartFrame();
9206 if (r_timereport_active)
9207 R_TimeReport("viewsetup");
9209 R_ResetViewRendering3D();
9211 if (r_refdef.view.clear || r_refdef.fogenabled)
9213 R_ClearScreen(r_refdef.fogenabled);
9214 if (r_timereport_active)
9215 R_TimeReport("viewclear");
9217 r_refdef.view.clear = true;
9219 // this produces a bloom texture to be used in R_BlendView() later
9220 if (r_hdr.integer && r_bloomstate.bloomwidth)
9222 R_HDR_RenderBloomTexture();
9223 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9224 r_textureframe++; // used only by R_GetCurrentTexture
9227 r_refdef.view.showdebug = true;
9230 if (r_timereport_active)
9231 R_TimeReport("visibility");
9233 r_waterstate.numwaterplanes = 0;
9234 if (r_waterstate.enabled)
9235 R_RenderWaterPlanes();
9238 r_waterstate.numwaterplanes = 0;
9241 if (r_timereport_active)
9242 R_TimeReport("blendview");
9244 GL_Scissor(0, 0, vid.width, vid.height);
9245 GL_ScissorTest(false);
9247 r_refdef.view.matrix = originalmatrix;
9252 void R_RenderWaterPlanes(void)
9254 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9256 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9257 if (r_timereport_active)
9258 R_TimeReport("waterworld");
9261 // don't let sound skip if going slow
9262 if (r_refdef.scene.extraupdate)
9265 R_DrawModelsAddWaterPlanes();
9266 if (r_timereport_active)
9267 R_TimeReport("watermodels");
9269 if (r_waterstate.numwaterplanes)
9271 R_Water_ProcessPlanes();
9272 if (r_timereport_active)
9273 R_TimeReport("waterscenes");
9277 extern void R_DrawLightningBeams (void);
9278 extern void VM_CL_AddPolygonsToMeshQueue (void);
9279 extern void R_DrawPortals (void);
9280 extern cvar_t cl_locs_show;
9281 static void R_DrawLocs(void);
9282 static void R_DrawEntityBBoxes(void);
9283 static void R_DrawModelDecals(void);
9284 extern void R_DrawModelShadows(void);
9285 extern void R_DrawModelShadowMaps(void);
9286 extern cvar_t cl_decals_newsystem;
9287 extern qboolean r_shadow_usingdeferredprepass;
9288 void R_RenderScene(void)
9290 qboolean shadowmapping = false;
9292 if (r_timereport_active)
9293 R_TimeReport("beginscene");
9295 r_refdef.stats.renders++;
9299 // don't let sound skip if going slow
9300 if (r_refdef.scene.extraupdate)
9303 R_MeshQueue_BeginScene();
9307 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);
9309 if (r_timereport_active)
9310 R_TimeReport("skystartframe");
9312 if (cl.csqc_vidvars.drawworld)
9314 // don't let sound skip if going slow
9315 if (r_refdef.scene.extraupdate)
9318 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9320 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9321 if (r_timereport_active)
9322 R_TimeReport("worldsky");
9325 if (R_DrawBrushModelsSky() && r_timereport_active)
9326 R_TimeReport("bmodelsky");
9328 if (skyrendermasked && skyrenderlater)
9330 // we have to force off the water clipping plane while rendering sky
9334 if (r_timereport_active)
9335 R_TimeReport("sky");
9339 R_AnimCache_CacheVisibleEntities();
9340 if (r_timereport_active)
9341 R_TimeReport("animation");
9343 R_Shadow_PrepareLights();
9344 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9345 R_Shadow_PrepareModelShadows();
9346 if (r_timereport_active)
9347 R_TimeReport("preparelights");
9349 if (R_Shadow_ShadowMappingEnabled())
9350 shadowmapping = true;
9352 if (r_shadow_usingdeferredprepass)
9353 R_Shadow_DrawPrepass();
9355 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9357 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9358 if (r_timereport_active)
9359 R_TimeReport("worlddepth");
9361 if (r_depthfirst.integer >= 2)
9363 R_DrawModelsDepth();
9364 if (r_timereport_active)
9365 R_TimeReport("modeldepth");
9368 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9370 R_DrawModelShadowMaps();
9371 R_ResetViewRendering3D();
9372 // don't let sound skip if going slow
9373 if (r_refdef.scene.extraupdate)
9377 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9379 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9380 if (r_timereport_active)
9381 R_TimeReport("world");
9384 // don't let sound skip if going slow
9385 if (r_refdef.scene.extraupdate)
9389 if (r_timereport_active)
9390 R_TimeReport("models");
9392 // don't let sound skip if going slow
9393 if (r_refdef.scene.extraupdate)
9396 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9398 R_DrawModelShadows();
9399 R_ResetViewRendering3D();
9400 // don't let sound skip if going slow
9401 if (r_refdef.scene.extraupdate)
9405 if (!r_shadow_usingdeferredprepass)
9407 R_Shadow_DrawLights();
9408 if (r_timereport_active)
9409 R_TimeReport("rtlights");
9412 // don't let sound skip if going slow
9413 if (r_refdef.scene.extraupdate)
9416 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9418 R_DrawModelShadows();
9419 R_ResetViewRendering3D();
9420 // don't let sound skip if going slow
9421 if (r_refdef.scene.extraupdate)
9425 if (cl.csqc_vidvars.drawworld)
9427 if (cl_decals_newsystem.integer)
9429 R_DrawModelDecals();
9430 if (r_timereport_active)
9431 R_TimeReport("modeldecals");
9436 if (r_timereport_active)
9437 R_TimeReport("decals");
9441 if (r_timereport_active)
9442 R_TimeReport("particles");
9445 if (r_timereport_active)
9446 R_TimeReport("explosions");
9448 R_DrawLightningBeams();
9449 if (r_timereport_active)
9450 R_TimeReport("lightning");
9453 VM_CL_AddPolygonsToMeshQueue();
9455 if (r_refdef.view.showdebug)
9457 if (cl_locs_show.integer)
9460 if (r_timereport_active)
9461 R_TimeReport("showlocs");
9464 if (r_drawportals.integer)
9467 if (r_timereport_active)
9468 R_TimeReport("portals");
9471 if (r_showbboxes.value > 0)
9473 R_DrawEntityBBoxes();
9474 if (r_timereport_active)
9475 R_TimeReport("bboxes");
9479 R_MeshQueue_RenderTransparent();
9480 if (r_timereport_active)
9481 R_TimeReport("drawtrans");
9483 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))
9485 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9486 if (r_timereport_active)
9487 R_TimeReport("worlddebug");
9488 R_DrawModelsDebug();
9489 if (r_timereport_active)
9490 R_TimeReport("modeldebug");
9493 if (cl.csqc_vidvars.drawworld)
9495 R_Shadow_DrawCoronas();
9496 if (r_timereport_active)
9497 R_TimeReport("coronas");
9502 GL_DepthTest(false);
9503 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9504 GL_Color(1, 1, 1, 1);
9505 qglBegin(GL_POLYGON);
9506 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
9507 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
9508 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
9509 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
9511 qglBegin(GL_POLYGON);
9512 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]);
9513 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]);
9514 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]);
9515 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]);
9517 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9521 // don't let sound skip if going slow
9522 if (r_refdef.scene.extraupdate)
9525 R_ResetViewRendering2D();
9528 static const unsigned short bboxelements[36] =
9538 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9541 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9543 RSurf_ActiveWorldEntity();
9545 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9546 GL_DepthMask(false);
9547 GL_DepthRange(0, 1);
9548 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9549 // R_Mesh_ResetTextureState();
9551 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9552 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9553 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9554 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9555 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9556 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9557 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9558 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9559 R_FillColors(color4f, 8, cr, cg, cb, ca);
9560 if (r_refdef.fogenabled)
9562 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9564 f1 = RSurf_FogVertex(v);
9566 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9567 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9568 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9571 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
9572 R_Mesh_ResetTextureState();
9573 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9574 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
9577 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9581 prvm_edict_t *edict;
9582 prvm_prog_t *prog_save = prog;
9584 // this function draws bounding boxes of server entities
9588 GL_CullFace(GL_NONE);
9589 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9593 for (i = 0;i < numsurfaces;i++)
9595 edict = PRVM_EDICT_NUM(surfacelist[i]);
9596 switch ((int)edict->fields.server->solid)
9598 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
9599 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
9600 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
9601 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9602 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
9603 default: Vector4Set(color, 0, 0, 0, 0.50);break;
9605 color[3] *= r_showbboxes.value;
9606 color[3] = bound(0, color[3], 1);
9607 GL_DepthTest(!r_showdisabledepthtest.integer);
9608 GL_CullFace(r_refdef.view.cullface_front);
9609 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
9615 static void R_DrawEntityBBoxes(void)
9618 prvm_edict_t *edict;
9620 prvm_prog_t *prog_save = prog;
9622 // this function draws bounding boxes of server entities
9628 for (i = 0;i < prog->num_edicts;i++)
9630 edict = PRVM_EDICT_NUM(i);
9631 if (edict->priv.server->free)
9633 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
9634 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
9636 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
9638 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
9639 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
9645 static const int nomodelelement3i[24] =
9657 static const unsigned short nomodelelement3s[24] =
9669 static const float nomodelvertex3f[6*3] =
9679 static const float nomodelcolor4f[6*4] =
9681 0.0f, 0.0f, 0.5f, 1.0f,
9682 0.0f, 0.0f, 0.5f, 1.0f,
9683 0.0f, 0.5f, 0.0f, 1.0f,
9684 0.0f, 0.5f, 0.0f, 1.0f,
9685 0.5f, 0.0f, 0.0f, 1.0f,
9686 0.5f, 0.0f, 0.0f, 1.0f
9689 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9695 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);
9697 // this is only called once per entity so numsurfaces is always 1, and
9698 // surfacelist is always {0}, so this code does not handle batches
9700 if (rsurface.ent_flags & RENDER_ADDITIVE)
9702 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
9703 GL_DepthMask(false);
9705 else if (rsurface.colormod[3] < 1)
9707 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9708 GL_DepthMask(false);
9712 GL_BlendFunc(GL_ONE, GL_ZERO);
9715 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
9716 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
9717 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
9718 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
9719 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
9720 for (i = 0, c = color4f;i < 6;i++, c += 4)
9722 c[0] *= rsurface.colormod[0];
9723 c[1] *= rsurface.colormod[1];
9724 c[2] *= rsurface.colormod[2];
9725 c[3] *= rsurface.colormod[3];
9727 if (r_refdef.fogenabled)
9729 for (i = 0, c = color4f;i < 6;i++, c += 4)
9731 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
9733 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
9734 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
9735 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
9738 // R_Mesh_ResetTextureState();
9739 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9740 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
9741 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
9744 void R_DrawNoModel(entity_render_t *ent)
9747 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
9748 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
9749 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
9751 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
9754 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
9756 vec3_t right1, right2, diff, normal;
9758 VectorSubtract (org2, org1, normal);
9760 // calculate 'right' vector for start
9761 VectorSubtract (r_refdef.view.origin, org1, diff);
9762 CrossProduct (normal, diff, right1);
9763 VectorNormalize (right1);
9765 // calculate 'right' vector for end
9766 VectorSubtract (r_refdef.view.origin, org2, diff);
9767 CrossProduct (normal, diff, right2);
9768 VectorNormalize (right2);
9770 vert[ 0] = org1[0] + width * right1[0];
9771 vert[ 1] = org1[1] + width * right1[1];
9772 vert[ 2] = org1[2] + width * right1[2];
9773 vert[ 3] = org1[0] - width * right1[0];
9774 vert[ 4] = org1[1] - width * right1[1];
9775 vert[ 5] = org1[2] - width * right1[2];
9776 vert[ 6] = org2[0] - width * right2[0];
9777 vert[ 7] = org2[1] - width * right2[1];
9778 vert[ 8] = org2[2] - width * right2[2];
9779 vert[ 9] = org2[0] + width * right2[0];
9780 vert[10] = org2[1] + width * right2[1];
9781 vert[11] = org2[2] + width * right2[2];
9784 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)
9786 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
9787 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
9788 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
9789 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
9790 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
9791 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
9792 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
9793 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
9794 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
9795 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
9796 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
9797 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
9800 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
9805 VectorSet(v, x, y, z);
9806 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
9807 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
9809 if (i == mesh->numvertices)
9811 if (mesh->numvertices < mesh->maxvertices)
9813 VectorCopy(v, vertex3f);
9814 mesh->numvertices++;
9816 return mesh->numvertices;
9822 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
9826 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9827 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9828 e = mesh->element3i + mesh->numtriangles * 3;
9829 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
9831 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
9832 if (mesh->numtriangles < mesh->maxtriangles)
9837 mesh->numtriangles++;
9839 element[1] = element[2];
9843 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
9847 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9848 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9849 e = mesh->element3i + mesh->numtriangles * 3;
9850 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
9852 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
9853 if (mesh->numtriangles < mesh->maxtriangles)
9858 mesh->numtriangles++;
9860 element[1] = element[2];
9864 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
9865 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
9867 int planenum, planenum2;
9870 mplane_t *plane, *plane2;
9872 double temppoints[2][256*3];
9873 // figure out how large a bounding box we need to properly compute this brush
9875 for (w = 0;w < numplanes;w++)
9876 maxdist = max(maxdist, fabs(planes[w].dist));
9877 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
9878 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
9879 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
9883 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
9884 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
9886 if (planenum2 == planenum)
9888 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);
9891 if (tempnumpoints < 3)
9893 // generate elements forming a triangle fan for this polygon
9894 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
9898 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)
9900 texturelayer_t *layer;
9901 layer = t->currentlayers + t->currentnumlayers++;
9903 layer->depthmask = depthmask;
9904 layer->blendfunc1 = blendfunc1;
9905 layer->blendfunc2 = blendfunc2;
9906 layer->texture = texture;
9907 layer->texmatrix = *matrix;
9908 layer->color[0] = r;
9909 layer->color[1] = g;
9910 layer->color[2] = b;
9911 layer->color[3] = a;
9914 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
9916 if(parms[0] == 0 && parms[1] == 0)
9918 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
9919 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
9924 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
9927 index = parms[2] + r_refdef.scene.time * parms[3];
9928 index -= floor(index);
9929 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
9932 case Q3WAVEFUNC_NONE:
9933 case Q3WAVEFUNC_NOISE:
9934 case Q3WAVEFUNC_COUNT:
9937 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
9938 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
9939 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
9940 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
9941 case Q3WAVEFUNC_TRIANGLE:
9943 f = index - floor(index);
9954 f = parms[0] + parms[1] * f;
9955 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
9956 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
9960 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
9965 matrix4x4_t matrix, temp;
9966 switch(tcmod->tcmod)
9970 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9971 matrix = r_waterscrollmatrix;
9973 matrix = identitymatrix;
9975 case Q3TCMOD_ENTITYTRANSLATE:
9976 // this is used in Q3 to allow the gamecode to control texcoord
9977 // scrolling on the entity, which is not supported in darkplaces yet.
9978 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
9980 case Q3TCMOD_ROTATE:
9981 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
9982 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
9983 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
9986 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
9988 case Q3TCMOD_SCROLL:
9989 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
9991 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
9992 w = (int) tcmod->parms[0];
9993 h = (int) tcmod->parms[1];
9994 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
9996 idx = (int) floor(f * w * h);
9997 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
9999 case Q3TCMOD_STRETCH:
10000 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10001 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10003 case Q3TCMOD_TRANSFORM:
10004 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
10005 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
10006 VectorSet(tcmat + 6, 0 , 0 , 1);
10007 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
10008 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10010 case Q3TCMOD_TURBULENT:
10011 // this is handled in the RSurf_PrepareVertices function
10012 matrix = identitymatrix;
10016 Matrix4x4_Concat(texmatrix, &matrix, &temp);
10019 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10021 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10022 char name[MAX_QPATH];
10023 skinframe_t *skinframe;
10024 unsigned char pixels[296*194];
10025 strlcpy(cache->name, skinname, sizeof(cache->name));
10026 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10027 if (developer_loading.integer)
10028 Con_Printf("loading %s\n", name);
10029 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10030 if (!skinframe || !skinframe->base)
10033 fs_offset_t filesize;
10035 f = FS_LoadFile(name, tempmempool, true, &filesize);
10038 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10039 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10043 cache->skinframe = skinframe;
10046 texture_t *R_GetCurrentTexture(texture_t *t)
10049 const entity_render_t *ent = rsurface.entity;
10050 dp_model_t *model = ent->model;
10051 q3shaderinfo_layer_tcmod_t *tcmod;
10053 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10054 return t->currentframe;
10055 t->update_lastrenderframe = r_textureframe;
10056 t->update_lastrenderentity = (void *)ent;
10058 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10059 t->camera_entity = ent->entitynumber;
10061 t->camera_entity = 0;
10063 // switch to an alternate material if this is a q1bsp animated material
10065 texture_t *texture = t;
10066 int s = rsurface.ent_skinnum;
10067 if ((unsigned int)s >= (unsigned int)model->numskins)
10069 if (model->skinscenes)
10071 if (model->skinscenes[s].framecount > 1)
10072 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10074 s = model->skinscenes[s].firstframe;
10077 t = t + s * model->num_surfaces;
10080 // use an alternate animation if the entity's frame is not 0,
10081 // and only if the texture has an alternate animation
10082 if (rsurface.ent_alttextures && t->anim_total[1])
10083 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10085 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10087 texture->currentframe = t;
10090 // update currentskinframe to be a qw skin or animation frame
10091 if (rsurface.ent_qwskin >= 0)
10093 i = rsurface.ent_qwskin;
10094 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10096 r_qwskincache_size = cl.maxclients;
10098 Mem_Free(r_qwskincache);
10099 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10101 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10102 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10103 t->currentskinframe = r_qwskincache[i].skinframe;
10104 if (t->currentskinframe == NULL)
10105 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10107 else if (t->numskinframes >= 2)
10108 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10109 if (t->backgroundnumskinframes >= 2)
10110 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10112 t->currentmaterialflags = t->basematerialflags;
10113 t->currentalpha = rsurface.colormod[3];
10114 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10115 t->currentalpha *= r_wateralpha.value;
10116 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10117 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10118 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10119 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10120 if (!(rsurface.ent_flags & RENDER_LIGHT))
10121 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10122 else if (FAKELIGHT_ENABLED)
10124 // no modellight if using fakelight for the map
10126 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10128 // pick a model lighting mode
10129 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10130 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10132 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10134 if (rsurface.ent_flags & RENDER_ADDITIVE)
10135 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10136 else if (t->currentalpha < 1)
10137 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10138 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10139 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10140 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10141 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10142 if (t->backgroundnumskinframes)
10143 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10144 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10146 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10147 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10150 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10151 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10152 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10154 // there is no tcmod
10155 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10157 t->currenttexmatrix = r_waterscrollmatrix;
10158 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10160 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10162 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10163 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10166 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10167 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10168 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10169 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10171 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10172 if (t->currentskinframe->qpixels)
10173 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10174 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10175 if (!t->basetexture)
10176 t->basetexture = r_texture_notexture;
10177 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10178 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10179 t->nmaptexture = t->currentskinframe->nmap;
10180 if (!t->nmaptexture)
10181 t->nmaptexture = r_texture_blanknormalmap;
10182 t->glosstexture = r_texture_black;
10183 t->glowtexture = t->currentskinframe->glow;
10184 t->fogtexture = t->currentskinframe->fog;
10185 t->reflectmasktexture = t->currentskinframe->reflect;
10186 if (t->backgroundnumskinframes)
10188 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10189 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10190 t->backgroundglosstexture = r_texture_black;
10191 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10192 if (!t->backgroundnmaptexture)
10193 t->backgroundnmaptexture = r_texture_blanknormalmap;
10197 t->backgroundbasetexture = r_texture_white;
10198 t->backgroundnmaptexture = r_texture_blanknormalmap;
10199 t->backgroundglosstexture = r_texture_black;
10200 t->backgroundglowtexture = NULL;
10202 t->specularpower = r_shadow_glossexponent.value;
10203 // TODO: store reference values for these in the texture?
10204 t->specularscale = 0;
10205 if (r_shadow_gloss.integer > 0)
10207 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10209 if (r_shadow_glossintensity.value > 0)
10211 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10212 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10213 t->specularscale = r_shadow_glossintensity.value;
10216 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10218 t->glosstexture = r_texture_white;
10219 t->backgroundglosstexture = r_texture_white;
10220 t->specularscale = r_shadow_gloss2intensity.value;
10221 t->specularpower = r_shadow_gloss2exponent.value;
10224 t->specularscale *= t->specularscalemod;
10225 t->specularpower *= t->specularpowermod;
10227 // lightmaps mode looks bad with dlights using actual texturing, so turn
10228 // off the colormap and glossmap, but leave the normalmap on as it still
10229 // accurately represents the shading involved
10230 if (gl_lightmaps.integer)
10232 t->basetexture = r_texture_grey128;
10233 t->pantstexture = r_texture_black;
10234 t->shirttexture = r_texture_black;
10235 t->nmaptexture = r_texture_blanknormalmap;
10236 t->glosstexture = r_texture_black;
10237 t->glowtexture = NULL;
10238 t->fogtexture = NULL;
10239 t->reflectmasktexture = NULL;
10240 t->backgroundbasetexture = NULL;
10241 t->backgroundnmaptexture = r_texture_blanknormalmap;
10242 t->backgroundglosstexture = r_texture_black;
10243 t->backgroundglowtexture = NULL;
10244 t->specularscale = 0;
10245 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10248 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10249 VectorClear(t->dlightcolor);
10250 t->currentnumlayers = 0;
10251 if (t->currentmaterialflags & MATERIALFLAG_WALL)
10253 int blendfunc1, blendfunc2;
10254 qboolean depthmask;
10255 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10257 blendfunc1 = GL_SRC_ALPHA;
10258 blendfunc2 = GL_ONE;
10260 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10262 blendfunc1 = GL_SRC_ALPHA;
10263 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10265 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10267 blendfunc1 = t->customblendfunc[0];
10268 blendfunc2 = t->customblendfunc[1];
10272 blendfunc1 = GL_ONE;
10273 blendfunc2 = GL_ZERO;
10275 // don't colormod evilblend textures
10276 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10277 VectorSet(t->lightmapcolor, 1, 1, 1);
10278 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10279 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10281 // fullbright is not affected by r_refdef.lightmapintensity
10282 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]);
10283 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10284 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]);
10285 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10286 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]);
10290 vec3_t ambientcolor;
10292 // set the color tint used for lights affecting this surface
10293 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10295 // q3bsp has no lightmap updates, so the lightstylevalue that
10296 // would normally be baked into the lightmap must be
10297 // applied to the color
10298 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10299 if (model->type == mod_brushq3)
10300 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10301 colorscale *= r_refdef.lightmapintensity;
10302 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10303 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10304 // basic lit geometry
10305 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]);
10306 // add pants/shirt if needed
10307 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10308 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]);
10309 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10310 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]);
10311 // now add ambient passes if needed
10312 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10314 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]);
10315 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10316 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]);
10317 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10318 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]);
10321 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10322 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]);
10323 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10325 // if this is opaque use alpha blend which will darken the earlier
10328 // if this is an alpha blended material, all the earlier passes
10329 // were darkened by fog already, so we only need to add the fog
10330 // color ontop through the fog mask texture
10332 // if this is an additive blended material, all the earlier passes
10333 // were darkened by fog already, and we should not add fog color
10334 // (because the background was not darkened, there is no fog color
10335 // that was lost behind it).
10336 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]);
10340 return t->currentframe;
10343 rsurfacestate_t rsurface;
10345 void RSurf_ActiveWorldEntity(void)
10347 dp_model_t *model = r_refdef.scene.worldmodel;
10348 //if (rsurface.entity == r_refdef.scene.worldentity)
10350 rsurface.entity = r_refdef.scene.worldentity;
10351 rsurface.skeleton = NULL;
10352 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10353 rsurface.ent_skinnum = 0;
10354 rsurface.ent_qwskin = -1;
10355 rsurface.ent_shadertime = 0;
10356 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10357 rsurface.matrix = identitymatrix;
10358 rsurface.inversematrix = identitymatrix;
10359 rsurface.matrixscale = 1;
10360 rsurface.inversematrixscale = 1;
10361 R_EntityMatrix(&identitymatrix);
10362 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10363 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10364 rsurface.fograngerecip = r_refdef.fograngerecip;
10365 rsurface.fogheightfade = r_refdef.fogheightfade;
10366 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10367 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10368 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10369 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10370 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10371 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10372 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10373 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10374 rsurface.colormod[3] = 1;
10375 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);
10376 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10377 rsurface.frameblend[0].lerp = 1;
10378 rsurface.ent_alttextures = false;
10379 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10380 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10381 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
10382 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10383 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10384 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10385 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10386 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10387 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10388 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10389 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10390 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
10391 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10392 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10393 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
10394 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10395 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10396 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
10397 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10398 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10399 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
10400 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10401 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10402 rsurface.modelelement3i = model->surfmesh.data_element3i;
10403 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10404 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10405 rsurface.modelelement3s = model->surfmesh.data_element3s;
10406 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10407 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10408 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10409 rsurface.modelnumvertices = model->surfmesh.num_vertices;
10410 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10411 rsurface.modelsurfaces = model->data_surfaces;
10412 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10413 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10414 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
10415 rsurface.modelgeneratedvertex = false;
10416 rsurface.batchgeneratedvertex = false;
10417 rsurface.batchfirstvertex = 0;
10418 rsurface.batchnumvertices = 0;
10419 rsurface.batchfirsttriangle = 0;
10420 rsurface.batchnumtriangles = 0;
10421 rsurface.batchvertex3f = NULL;
10422 rsurface.batchvertex3f_vertexbuffer = NULL;
10423 rsurface.batchvertex3f_bufferoffset = 0;
10424 rsurface.batchsvector3f = NULL;
10425 rsurface.batchsvector3f_vertexbuffer = NULL;
10426 rsurface.batchsvector3f_bufferoffset = 0;
10427 rsurface.batchtvector3f = NULL;
10428 rsurface.batchtvector3f_vertexbuffer = NULL;
10429 rsurface.batchtvector3f_bufferoffset = 0;
10430 rsurface.batchnormal3f = NULL;
10431 rsurface.batchnormal3f_vertexbuffer = NULL;
10432 rsurface.batchnormal3f_bufferoffset = 0;
10433 rsurface.batchlightmapcolor4f = NULL;
10434 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10435 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10436 rsurface.batchtexcoordtexture2f = NULL;
10437 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10438 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10439 rsurface.batchtexcoordlightmap2f = NULL;
10440 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10441 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10442 rsurface.batchvertexmesh = NULL;
10443 rsurface.batchvertexmeshbuffer = NULL;
10444 rsurface.batchvertex3fbuffer = NULL;
10445 rsurface.batchelement3i = NULL;
10446 rsurface.batchelement3i_indexbuffer = NULL;
10447 rsurface.batchelement3i_bufferoffset = 0;
10448 rsurface.batchelement3s = NULL;
10449 rsurface.batchelement3s_indexbuffer = NULL;
10450 rsurface.batchelement3s_bufferoffset = 0;
10451 rsurface.passcolor4f = NULL;
10452 rsurface.passcolor4f_vertexbuffer = NULL;
10453 rsurface.passcolor4f_bufferoffset = 0;
10456 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10458 dp_model_t *model = ent->model;
10459 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10461 rsurface.entity = (entity_render_t *)ent;
10462 rsurface.skeleton = ent->skeleton;
10463 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10464 rsurface.ent_skinnum = ent->skinnum;
10465 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;
10466 rsurface.ent_shadertime = ent->shadertime;
10467 rsurface.ent_flags = ent->flags;
10468 rsurface.matrix = ent->matrix;
10469 rsurface.inversematrix = ent->inversematrix;
10470 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10471 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10472 R_EntityMatrix(&rsurface.matrix);
10473 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10474 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10475 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10476 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10477 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10478 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10479 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10480 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10481 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10482 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10483 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10484 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10485 rsurface.colormod[3] = ent->alpha;
10486 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10487 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10488 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10489 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10490 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10491 if (ent->model->brush.submodel && !prepass)
10493 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10494 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10496 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10498 if (ent->animcache_vertex3f)
10500 rsurface.modelvertex3f = ent->animcache_vertex3f;
10501 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10502 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10503 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10504 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
10505 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
10506 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
10508 else if (wanttangents)
10510 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10511 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10512 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10513 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10514 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
10515 rsurface.modelvertexmesh = NULL;
10516 rsurface.modelvertexmeshbuffer = NULL;
10517 rsurface.modelvertex3fbuffer = NULL;
10519 else if (wantnormals)
10521 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10522 rsurface.modelsvector3f = NULL;
10523 rsurface.modeltvector3f = NULL;
10524 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10525 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
10526 rsurface.modelvertexmesh = NULL;
10527 rsurface.modelvertexmeshbuffer = NULL;
10528 rsurface.modelvertex3fbuffer = NULL;
10532 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10533 rsurface.modelsvector3f = NULL;
10534 rsurface.modeltvector3f = NULL;
10535 rsurface.modelnormal3f = NULL;
10536 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
10537 rsurface.modelvertexmesh = NULL;
10538 rsurface.modelvertexmeshbuffer = NULL;
10539 rsurface.modelvertex3fbuffer = NULL;
10541 rsurface.modelvertex3f_vertexbuffer = 0;
10542 rsurface.modelvertex3f_bufferoffset = 0;
10543 rsurface.modelsvector3f_vertexbuffer = 0;
10544 rsurface.modelsvector3f_bufferoffset = 0;
10545 rsurface.modeltvector3f_vertexbuffer = 0;
10546 rsurface.modeltvector3f_bufferoffset = 0;
10547 rsurface.modelnormal3f_vertexbuffer = 0;
10548 rsurface.modelnormal3f_bufferoffset = 0;
10549 rsurface.modelgeneratedvertex = true;
10553 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
10554 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10555 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10556 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10557 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10558 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10559 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10560 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10561 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10562 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
10563 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10564 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10565 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10566 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10567 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
10568 rsurface.modelgeneratedvertex = false;
10570 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
10571 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10572 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10573 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
10574 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10575 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10576 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
10577 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10578 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10579 rsurface.modelelement3i = model->surfmesh.data_element3i;
10580 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10581 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10582 rsurface.modelelement3s = model->surfmesh.data_element3s;
10583 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10584 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10585 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10586 rsurface.modelnumvertices = model->surfmesh.num_vertices;
10587 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10588 rsurface.modelsurfaces = model->data_surfaces;
10589 rsurface.batchgeneratedvertex = false;
10590 rsurface.batchfirstvertex = 0;
10591 rsurface.batchnumvertices = 0;
10592 rsurface.batchfirsttriangle = 0;
10593 rsurface.batchnumtriangles = 0;
10594 rsurface.batchvertex3f = NULL;
10595 rsurface.batchvertex3f_vertexbuffer = NULL;
10596 rsurface.batchvertex3f_bufferoffset = 0;
10597 rsurface.batchsvector3f = NULL;
10598 rsurface.batchsvector3f_vertexbuffer = NULL;
10599 rsurface.batchsvector3f_bufferoffset = 0;
10600 rsurface.batchtvector3f = NULL;
10601 rsurface.batchtvector3f_vertexbuffer = NULL;
10602 rsurface.batchtvector3f_bufferoffset = 0;
10603 rsurface.batchnormal3f = NULL;
10604 rsurface.batchnormal3f_vertexbuffer = NULL;
10605 rsurface.batchnormal3f_bufferoffset = 0;
10606 rsurface.batchlightmapcolor4f = NULL;
10607 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10608 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10609 rsurface.batchtexcoordtexture2f = NULL;
10610 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10611 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10612 rsurface.batchtexcoordlightmap2f = NULL;
10613 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10614 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10615 rsurface.batchvertexmesh = NULL;
10616 rsurface.batchvertexmeshbuffer = NULL;
10617 rsurface.batchvertex3fbuffer = NULL;
10618 rsurface.batchelement3i = NULL;
10619 rsurface.batchelement3i_indexbuffer = NULL;
10620 rsurface.batchelement3i_bufferoffset = 0;
10621 rsurface.batchelement3s = NULL;
10622 rsurface.batchelement3s_indexbuffer = NULL;
10623 rsurface.batchelement3s_bufferoffset = 0;
10624 rsurface.passcolor4f = NULL;
10625 rsurface.passcolor4f_vertexbuffer = NULL;
10626 rsurface.passcolor4f_bufferoffset = 0;
10629 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)
10631 rsurface.entity = r_refdef.scene.worldentity;
10632 rsurface.skeleton = NULL;
10633 rsurface.ent_skinnum = 0;
10634 rsurface.ent_qwskin = -1;
10635 rsurface.ent_shadertime = shadertime;
10636 rsurface.ent_flags = entflags;
10637 rsurface.modelnumvertices = numvertices;
10638 rsurface.modelnumtriangles = numtriangles;
10639 rsurface.matrix = *matrix;
10640 rsurface.inversematrix = *inversematrix;
10641 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10642 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10643 R_EntityMatrix(&rsurface.matrix);
10644 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10645 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10646 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10647 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10648 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10649 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10650 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10651 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10652 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10653 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10654 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10655 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
10656 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);
10657 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10658 rsurface.frameblend[0].lerp = 1;
10659 rsurface.ent_alttextures = false;
10660 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10661 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10664 rsurface.modelvertex3f = (float *)vertex3f;
10665 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10666 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10667 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10669 else if (wantnormals)
10671 rsurface.modelvertex3f = (float *)vertex3f;
10672 rsurface.modelsvector3f = NULL;
10673 rsurface.modeltvector3f = NULL;
10674 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10678 rsurface.modelvertex3f = (float *)vertex3f;
10679 rsurface.modelsvector3f = NULL;
10680 rsurface.modeltvector3f = NULL;
10681 rsurface.modelnormal3f = NULL;
10683 rsurface.modelvertexmesh = NULL;
10684 rsurface.modelvertexmeshbuffer = NULL;
10685 rsurface.modelvertex3fbuffer = NULL;
10686 rsurface.modelvertex3f_vertexbuffer = 0;
10687 rsurface.modelvertex3f_bufferoffset = 0;
10688 rsurface.modelsvector3f_vertexbuffer = 0;
10689 rsurface.modelsvector3f_bufferoffset = 0;
10690 rsurface.modeltvector3f_vertexbuffer = 0;
10691 rsurface.modeltvector3f_bufferoffset = 0;
10692 rsurface.modelnormal3f_vertexbuffer = 0;
10693 rsurface.modelnormal3f_bufferoffset = 0;
10694 rsurface.modelgeneratedvertex = true;
10695 rsurface.modellightmapcolor4f = (float *)color4f;
10696 rsurface.modellightmapcolor4f_vertexbuffer = 0;
10697 rsurface.modellightmapcolor4f_bufferoffset = 0;
10698 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
10699 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
10700 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
10701 rsurface.modeltexcoordlightmap2f = NULL;
10702 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
10703 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
10704 rsurface.modelelement3i = (int *)element3i;
10705 rsurface.modelelement3i_indexbuffer = NULL;
10706 rsurface.modelelement3i_bufferoffset = 0;
10707 rsurface.modelelement3s = (unsigned short *)element3s;
10708 rsurface.modelelement3s_indexbuffer = NULL;
10709 rsurface.modelelement3s_bufferoffset = 0;
10710 rsurface.modellightmapoffsets = NULL;
10711 rsurface.modelsurfaces = NULL;
10712 rsurface.batchgeneratedvertex = false;
10713 rsurface.batchfirstvertex = 0;
10714 rsurface.batchnumvertices = 0;
10715 rsurface.batchfirsttriangle = 0;
10716 rsurface.batchnumtriangles = 0;
10717 rsurface.batchvertex3f = NULL;
10718 rsurface.batchvertex3f_vertexbuffer = NULL;
10719 rsurface.batchvertex3f_bufferoffset = 0;
10720 rsurface.batchsvector3f = NULL;
10721 rsurface.batchsvector3f_vertexbuffer = NULL;
10722 rsurface.batchsvector3f_bufferoffset = 0;
10723 rsurface.batchtvector3f = NULL;
10724 rsurface.batchtvector3f_vertexbuffer = NULL;
10725 rsurface.batchtvector3f_bufferoffset = 0;
10726 rsurface.batchnormal3f = NULL;
10727 rsurface.batchnormal3f_vertexbuffer = NULL;
10728 rsurface.batchnormal3f_bufferoffset = 0;
10729 rsurface.batchlightmapcolor4f = NULL;
10730 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10731 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10732 rsurface.batchtexcoordtexture2f = NULL;
10733 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10734 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10735 rsurface.batchtexcoordlightmap2f = NULL;
10736 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10737 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10738 rsurface.batchvertexmesh = NULL;
10739 rsurface.batchvertexmeshbuffer = NULL;
10740 rsurface.batchvertex3fbuffer = NULL;
10741 rsurface.batchelement3i = NULL;
10742 rsurface.batchelement3i_indexbuffer = NULL;
10743 rsurface.batchelement3i_bufferoffset = 0;
10744 rsurface.batchelement3s = NULL;
10745 rsurface.batchelement3s_indexbuffer = NULL;
10746 rsurface.batchelement3s_bufferoffset = 0;
10747 rsurface.passcolor4f = NULL;
10748 rsurface.passcolor4f_vertexbuffer = NULL;
10749 rsurface.passcolor4f_bufferoffset = 0;
10751 if (rsurface.modelnumvertices && rsurface.modelelement3i)
10753 if ((wantnormals || wanttangents) && !normal3f)
10755 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10756 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
10758 if (wanttangents && !svector3f)
10760 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10761 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10762 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
10767 float RSurf_FogPoint(const float *v)
10769 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10770 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
10771 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
10772 float FogHeightFade = r_refdef.fogheightfade;
10774 unsigned int fogmasktableindex;
10775 if (r_refdef.fogplaneviewabove)
10776 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10778 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10779 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
10780 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10783 float RSurf_FogVertex(const float *v)
10785 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10786 float FogPlaneViewDist = rsurface.fogplaneviewdist;
10787 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
10788 float FogHeightFade = rsurface.fogheightfade;
10790 unsigned int fogmasktableindex;
10791 if (r_refdef.fogplaneviewabove)
10792 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10794 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10795 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
10796 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10799 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
10802 for (i = 0;i < numelements;i++)
10803 outelement3i[i] = inelement3i[i] + adjust;
10806 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
10807 extern cvar_t gl_vbo;
10808 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
10816 int surfacefirsttriangle;
10817 int surfacenumtriangles;
10818 int surfacefirstvertex;
10819 int surfaceendvertex;
10820 int surfacenumvertices;
10821 int batchnumvertices;
10822 int batchnumtriangles;
10826 qboolean dynamicvertex;
10830 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
10831 float waveparms[4];
10832 q3shaderinfo_deform_t *deform;
10833 const msurface_t *surface, *firstsurface;
10834 r_vertexmesh_t *vertexmesh;
10835 if (!texturenumsurfaces)
10837 // find vertex range of this surface batch
10839 firstsurface = texturesurfacelist[0];
10840 firsttriangle = firstsurface->num_firsttriangle;
10841 batchnumvertices = 0;
10842 batchnumtriangles = 0;
10843 firstvertex = endvertex = firstsurface->num_firstvertex;
10844 for (i = 0;i < texturenumsurfaces;i++)
10846 surface = texturesurfacelist[i];
10847 if (surface != firstsurface + i)
10849 surfacefirstvertex = surface->num_firstvertex;
10850 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
10851 surfacenumvertices = surface->num_vertices;
10852 surfacenumtriangles = surface->num_triangles;
10853 if (firstvertex > surfacefirstvertex)
10854 firstvertex = surfacefirstvertex;
10855 if (endvertex < surfaceendvertex)
10856 endvertex = surfaceendvertex;
10857 batchnumvertices += surfacenumvertices;
10858 batchnumtriangles += surfacenumtriangles;
10861 // we now know the vertex range used, and if there are any gaps in it
10862 rsurface.batchfirstvertex = firstvertex;
10863 rsurface.batchnumvertices = endvertex - firstvertex;
10864 rsurface.batchfirsttriangle = firsttriangle;
10865 rsurface.batchnumtriangles = batchnumtriangles;
10867 // this variable holds flags for which properties have been updated that
10868 // may require regenerating vertexmesh array...
10871 // check if any dynamic vertex processing must occur
10872 dynamicvertex = false;
10874 // if there is a chance of animated vertex colors, it's a dynamic batch
10875 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
10877 dynamicvertex = true;
10878 batchneed |= BATCHNEED_NOGAPS;
10879 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
10882 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
10884 switch (deform->deform)
10887 case Q3DEFORM_PROJECTIONSHADOW:
10888 case Q3DEFORM_TEXT0:
10889 case Q3DEFORM_TEXT1:
10890 case Q3DEFORM_TEXT2:
10891 case Q3DEFORM_TEXT3:
10892 case Q3DEFORM_TEXT4:
10893 case Q3DEFORM_TEXT5:
10894 case Q3DEFORM_TEXT6:
10895 case Q3DEFORM_TEXT7:
10896 case Q3DEFORM_NONE:
10898 case Q3DEFORM_AUTOSPRITE:
10899 dynamicvertex = true;
10900 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10901 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10903 case Q3DEFORM_AUTOSPRITE2:
10904 dynamicvertex = true;
10905 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10906 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10908 case Q3DEFORM_NORMAL:
10909 dynamicvertex = true;
10910 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10911 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10913 case Q3DEFORM_WAVE:
10914 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10915 break; // if wavefunc is a nop, ignore this transform
10916 dynamicvertex = true;
10917 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10918 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10920 case Q3DEFORM_BULGE:
10921 dynamicvertex = true;
10922 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10923 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10925 case Q3DEFORM_MOVE:
10926 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10927 break; // if wavefunc is a nop, ignore this transform
10928 dynamicvertex = true;
10929 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
10930 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
10934 switch(rsurface.texture->tcgen.tcgen)
10937 case Q3TCGEN_TEXTURE:
10939 case Q3TCGEN_LIGHTMAP:
10940 dynamicvertex = true;
10941 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
10942 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
10944 case Q3TCGEN_VECTOR:
10945 dynamicvertex = true;
10946 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
10947 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
10949 case Q3TCGEN_ENVIRONMENT:
10950 dynamicvertex = true;
10951 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
10952 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
10955 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10957 dynamicvertex = true;
10958 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10959 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
10962 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
10964 dynamicvertex = true;
10965 batchneed |= BATCHNEED_NOGAPS;
10966 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
10969 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
10971 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
10972 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
10973 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
10974 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
10975 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
10976 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
10977 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
10980 // when the model data has no vertex buffer (dynamic mesh), we need to
10982 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
10983 batchneed |= BATCHNEED_NOGAPS;
10985 // if needsupdate, we have to do a dynamic vertex batch for sure
10986 if (needsupdate & batchneed)
10987 dynamicvertex = true;
10989 // see if we need to build vertexmesh from arrays
10990 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
10991 dynamicvertex = true;
10993 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
10994 // also some drivers strongly dislike firstvertex
10995 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
10996 dynamicvertex = true;
10998 rsurface.batchvertex3f = rsurface.modelvertex3f;
10999 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11000 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11001 rsurface.batchsvector3f = rsurface.modelsvector3f;
11002 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11003 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11004 rsurface.batchtvector3f = rsurface.modeltvector3f;
11005 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11006 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11007 rsurface.batchnormal3f = rsurface.modelnormal3f;
11008 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11009 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11010 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11011 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
11012 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11013 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11014 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
11015 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
11016 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11017 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11018 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11019 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
11020 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11021 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11022 rsurface.batchelement3i = rsurface.modelelement3i;
11023 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11024 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11025 rsurface.batchelement3s = rsurface.modelelement3s;
11026 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11027 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11029 // if any dynamic vertex processing has to occur in software, we copy the
11030 // entire surface list together before processing to rebase the vertices
11031 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11033 // if any gaps exist and we do not have a static vertex buffer, we have to
11034 // copy the surface list together to avoid wasting upload bandwidth on the
11035 // vertices in the gaps.
11037 // if gaps exist and we have a static vertex buffer, we still have to
11038 // combine the index buffer ranges into one dynamic index buffer.
11040 // in all cases we end up with data that can be drawn in one call.
11042 if (!dynamicvertex)
11044 // static vertex data, just set pointers...
11045 rsurface.batchgeneratedvertex = false;
11046 // if there are gaps, we want to build a combined index buffer,
11047 // otherwise use the original static buffer with an appropriate offset
11050 // build a new triangle elements array for this batch
11051 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11052 rsurface.batchfirsttriangle = 0;
11054 for (i = 0;i < texturenumsurfaces;i++)
11056 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11057 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11058 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11059 numtriangles += surfacenumtriangles;
11061 rsurface.batchelement3i_indexbuffer = NULL;
11062 rsurface.batchelement3i_bufferoffset = 0;
11063 rsurface.batchelement3s = NULL;
11064 rsurface.batchelement3s_indexbuffer = NULL;
11065 rsurface.batchelement3s_bufferoffset = 0;
11066 if (endvertex <= 65536)
11068 // make a 16bit (unsigned short) index array if possible
11069 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11070 for (i = 0;i < numtriangles*3;i++)
11071 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11077 // something needs software processing, do it for real...
11078 // we only directly handle separate array data in this case and then
11079 // generate interleaved data if needed...
11080 rsurface.batchgeneratedvertex = true;
11082 // now copy the vertex data into a combined array and make an index array
11083 // (this is what Quake3 does all the time)
11084 //if (gaps || rsurface.batchfirstvertex)
11086 rsurface.batchvertex3fbuffer = NULL;
11087 rsurface.batchvertexmesh = NULL;
11088 rsurface.batchvertexmeshbuffer = NULL;
11089 rsurface.batchvertex3f = NULL;
11090 rsurface.batchvertex3f_vertexbuffer = NULL;
11091 rsurface.batchvertex3f_bufferoffset = 0;
11092 rsurface.batchsvector3f = NULL;
11093 rsurface.batchsvector3f_vertexbuffer = NULL;
11094 rsurface.batchsvector3f_bufferoffset = 0;
11095 rsurface.batchtvector3f = NULL;
11096 rsurface.batchtvector3f_vertexbuffer = NULL;
11097 rsurface.batchtvector3f_bufferoffset = 0;
11098 rsurface.batchnormal3f = NULL;
11099 rsurface.batchnormal3f_vertexbuffer = NULL;
11100 rsurface.batchnormal3f_bufferoffset = 0;
11101 rsurface.batchlightmapcolor4f = NULL;
11102 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11103 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11104 rsurface.batchtexcoordtexture2f = NULL;
11105 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11106 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11107 rsurface.batchtexcoordlightmap2f = NULL;
11108 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11109 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11110 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11111 rsurface.batchelement3i_indexbuffer = NULL;
11112 rsurface.batchelement3i_bufferoffset = 0;
11113 rsurface.batchelement3s = NULL;
11114 rsurface.batchelement3s_indexbuffer = NULL;
11115 rsurface.batchelement3s_bufferoffset = 0;
11116 // we'll only be setting up certain arrays as needed
11117 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11118 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
11119 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11120 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11121 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11122 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11123 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11125 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11126 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11128 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11129 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11130 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11131 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11132 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11133 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11136 for (i = 0;i < texturenumsurfaces;i++)
11138 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11139 surfacenumvertices = texturesurfacelist[i]->num_vertices;
11140 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11141 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11142 // copy only the data requested
11143 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11144 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11145 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11147 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11148 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11149 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11150 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11151 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11153 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11154 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11156 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11157 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11158 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11159 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11160 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11161 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11163 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11164 numvertices += surfacenumvertices;
11165 numtriangles += surfacenumtriangles;
11168 // generate a 16bit index array as well if possible
11169 // (in general, dynamic batches fit)
11170 if (numvertices <= 65536)
11172 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11173 for (i = 0;i < numtriangles*3;i++)
11174 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11177 // since we've copied everything, the batch now starts at 0
11178 rsurface.batchfirstvertex = 0;
11179 rsurface.batchnumvertices = batchnumvertices;
11180 rsurface.batchfirsttriangle = 0;
11181 rsurface.batchnumtriangles = batchnumtriangles;
11184 // q1bsp surfaces rendered in vertex color mode have to have colors
11185 // calculated based on lightstyles
11186 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11188 // generate color arrays for the surfaces in this list
11192 const int *offsets;
11193 const unsigned char *lm;
11194 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11195 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11196 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11198 for (i = 0;i < texturenumsurfaces;i++)
11200 surface = texturesurfacelist[i];
11201 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11202 surfacenumvertices = surface->num_vertices;
11203 if (surface->lightmapinfo->samples)
11205 for (j = 0;j < surfacenumvertices;j++)
11207 lm = surface->lightmapinfo->samples + offsets[j];
11208 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11209 VectorScale(lm, scale, c);
11210 if (surface->lightmapinfo->styles[1] != 255)
11212 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11214 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11215 VectorMA(c, scale, lm, c);
11216 if (surface->lightmapinfo->styles[2] != 255)
11219 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11220 VectorMA(c, scale, lm, c);
11221 if (surface->lightmapinfo->styles[3] != 255)
11224 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11225 VectorMA(c, scale, lm, c);
11232 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);
11238 for (j = 0;j < surfacenumvertices;j++)
11240 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11247 // if vertices are deformed (sprite flares and things in maps, possibly
11248 // water waves, bulges and other deformations), modify the copied vertices
11250 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11252 switch (deform->deform)
11255 case Q3DEFORM_PROJECTIONSHADOW:
11256 case Q3DEFORM_TEXT0:
11257 case Q3DEFORM_TEXT1:
11258 case Q3DEFORM_TEXT2:
11259 case Q3DEFORM_TEXT3:
11260 case Q3DEFORM_TEXT4:
11261 case Q3DEFORM_TEXT5:
11262 case Q3DEFORM_TEXT6:
11263 case Q3DEFORM_TEXT7:
11264 case Q3DEFORM_NONE:
11266 case Q3DEFORM_AUTOSPRITE:
11267 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11268 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11269 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11270 VectorNormalize(newforward);
11271 VectorNormalize(newright);
11272 VectorNormalize(newup);
11273 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11274 // rsurface.batchvertex3f_vertexbuffer = NULL;
11275 // rsurface.batchvertex3f_bufferoffset = 0;
11276 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
11277 // rsurface.batchsvector3f_vertexbuffer = NULL;
11278 // rsurface.batchsvector3f_bufferoffset = 0;
11279 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
11280 // rsurface.batchtvector3f_vertexbuffer = NULL;
11281 // rsurface.batchtvector3f_bufferoffset = 0;
11282 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11283 // rsurface.batchnormal3f_vertexbuffer = NULL;
11284 // rsurface.batchnormal3f_bufferoffset = 0;
11285 // a single autosprite surface can contain multiple sprites...
11286 for (j = 0;j < batchnumvertices - 3;j += 4)
11288 VectorClear(center);
11289 for (i = 0;i < 4;i++)
11290 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11291 VectorScale(center, 0.25f, center);
11292 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11293 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11294 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11295 for (i = 0;i < 4;i++)
11297 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11298 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
11301 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11302 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11303 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);
11305 case Q3DEFORM_AUTOSPRITE2:
11306 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11307 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11308 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11309 VectorNormalize(newforward);
11310 VectorNormalize(newright);
11311 VectorNormalize(newup);
11312 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11313 // rsurface.batchvertex3f_vertexbuffer = NULL;
11314 // rsurface.batchvertex3f_bufferoffset = 0;
11316 const float *v1, *v2;
11326 memset(shortest, 0, sizeof(shortest));
11327 // a single autosprite surface can contain multiple sprites...
11328 for (j = 0;j < batchnumvertices - 3;j += 4)
11330 VectorClear(center);
11331 for (i = 0;i < 4;i++)
11332 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11333 VectorScale(center, 0.25f, center);
11334 // find the two shortest edges, then use them to define the
11335 // axis vectors for rotating around the central axis
11336 for (i = 0;i < 6;i++)
11338 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11339 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11340 l = VectorDistance2(v1, v2);
11341 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11342 if (v1[2] != v2[2])
11343 l += (1.0f / 1024.0f);
11344 if (shortest[0].length2 > l || i == 0)
11346 shortest[1] = shortest[0];
11347 shortest[0].length2 = l;
11348 shortest[0].v1 = v1;
11349 shortest[0].v2 = v2;
11351 else if (shortest[1].length2 > l || i == 1)
11353 shortest[1].length2 = l;
11354 shortest[1].v1 = v1;
11355 shortest[1].v2 = v2;
11358 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11359 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11360 // this calculates the right vector from the shortest edge
11361 // and the up vector from the edge midpoints
11362 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11363 VectorNormalize(right);
11364 VectorSubtract(end, start, up);
11365 VectorNormalize(up);
11366 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11367 VectorSubtract(rsurface.localvieworigin, center, forward);
11368 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11369 VectorNegate(forward, forward);
11370 VectorReflect(forward, 0, up, forward);
11371 VectorNormalize(forward);
11372 CrossProduct(up, forward, newright);
11373 VectorNormalize(newright);
11374 // rotate the quad around the up axis vector, this is made
11375 // especially easy by the fact we know the quad is flat,
11376 // so we only have to subtract the center position and
11377 // measure distance along the right vector, and then
11378 // multiply that by the newright vector and add back the
11380 // we also need to subtract the old position to undo the
11381 // displacement from the center, which we do with a
11382 // DotProduct, the subtraction/addition of center is also
11383 // optimized into DotProducts here
11384 l = DotProduct(right, center);
11385 for (i = 0;i < 4;i++)
11387 v1 = rsurface.batchvertex3f + 3*(j+i);
11388 f = DotProduct(right, v1) - l;
11389 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
11393 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11395 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11396 // rsurface.batchnormal3f_vertexbuffer = NULL;
11397 // rsurface.batchnormal3f_bufferoffset = 0;
11398 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11400 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11402 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11403 // rsurface.batchsvector3f_vertexbuffer = NULL;
11404 // rsurface.batchsvector3f_bufferoffset = 0;
11405 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11406 // rsurface.batchtvector3f_vertexbuffer = NULL;
11407 // rsurface.batchtvector3f_bufferoffset = 0;
11408 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);
11411 case Q3DEFORM_NORMAL:
11412 // deform the normals to make reflections wavey
11413 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11414 rsurface.batchnormal3f_vertexbuffer = NULL;
11415 rsurface.batchnormal3f_bufferoffset = 0;
11416 for (j = 0;j < batchnumvertices;j++)
11419 float *normal = rsurface.batchnormal3f + 3*j;
11420 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11421 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11422 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]);
11423 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]);
11424 VectorNormalize(normal);
11426 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11428 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11429 // rsurface.batchsvector3f_vertexbuffer = NULL;
11430 // rsurface.batchsvector3f_bufferoffset = 0;
11431 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11432 // rsurface.batchtvector3f_vertexbuffer = NULL;
11433 // rsurface.batchtvector3f_bufferoffset = 0;
11434 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);
11437 case Q3DEFORM_WAVE:
11438 // deform vertex array to make wavey water and flags and such
11439 waveparms[0] = deform->waveparms[0];
11440 waveparms[1] = deform->waveparms[1];
11441 waveparms[2] = deform->waveparms[2];
11442 waveparms[3] = deform->waveparms[3];
11443 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11444 break; // if wavefunc is a nop, don't make a dynamic vertex array
11445 // this is how a divisor of vertex influence on deformation
11446 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11447 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11448 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11449 // rsurface.batchvertex3f_vertexbuffer = NULL;
11450 // rsurface.batchvertex3f_bufferoffset = 0;
11451 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11452 // rsurface.batchnormal3f_vertexbuffer = NULL;
11453 // rsurface.batchnormal3f_bufferoffset = 0;
11454 for (j = 0;j < batchnumvertices;j++)
11456 // if the wavefunc depends on time, evaluate it per-vertex
11459 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11460 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11462 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
11464 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11465 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11466 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11468 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11469 // rsurface.batchsvector3f_vertexbuffer = NULL;
11470 // rsurface.batchsvector3f_bufferoffset = 0;
11471 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11472 // rsurface.batchtvector3f_vertexbuffer = NULL;
11473 // rsurface.batchtvector3f_bufferoffset = 0;
11474 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);
11477 case Q3DEFORM_BULGE:
11478 // deform vertex array to make the surface have moving bulges
11479 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11480 // rsurface.batchvertex3f_vertexbuffer = NULL;
11481 // rsurface.batchvertex3f_bufferoffset = 0;
11482 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11483 // rsurface.batchnormal3f_vertexbuffer = NULL;
11484 // rsurface.batchnormal3f_bufferoffset = 0;
11485 for (j = 0;j < batchnumvertices;j++)
11487 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
11488 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
11490 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11491 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11492 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11494 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11495 // rsurface.batchsvector3f_vertexbuffer = NULL;
11496 // rsurface.batchsvector3f_bufferoffset = 0;
11497 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11498 // rsurface.batchtvector3f_vertexbuffer = NULL;
11499 // rsurface.batchtvector3f_bufferoffset = 0;
11500 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);
11503 case Q3DEFORM_MOVE:
11504 // deform vertex array
11505 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11506 break; // if wavefunc is a nop, don't make a dynamic vertex array
11507 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
11508 VectorScale(deform->parms, scale, waveparms);
11509 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11510 // rsurface.batchvertex3f_vertexbuffer = NULL;
11511 // rsurface.batchvertex3f_bufferoffset = 0;
11512 for (j = 0;j < batchnumvertices;j++)
11513 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
11518 // generate texcoords based on the chosen texcoord source
11519 switch(rsurface.texture->tcgen.tcgen)
11522 case Q3TCGEN_TEXTURE:
11524 case Q3TCGEN_LIGHTMAP:
11525 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11526 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11527 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11528 if (rsurface.batchtexcoordlightmap2f)
11529 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
11531 case Q3TCGEN_VECTOR:
11532 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11533 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11534 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11535 for (j = 0;j < batchnumvertices;j++)
11537 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
11538 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
11541 case Q3TCGEN_ENVIRONMENT:
11542 // make environment reflections using a spheremap
11543 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11544 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11545 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11546 for (j = 0;j < batchnumvertices;j++)
11548 // identical to Q3A's method, but executed in worldspace so
11549 // carried models can be shiny too
11551 float viewer[3], d, reflected[3], worldreflected[3];
11553 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
11554 // VectorNormalize(viewer);
11556 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
11558 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
11559 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
11560 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
11561 // note: this is proportinal to viewer, so we can normalize later
11563 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
11564 VectorNormalize(worldreflected);
11566 // note: this sphere map only uses world x and z!
11567 // so positive and negative y will LOOK THE SAME.
11568 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
11569 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
11573 // the only tcmod that needs software vertex processing is turbulent, so
11574 // check for it here and apply the changes if needed
11575 // and we only support that as the first one
11576 // (handling a mixture of turbulent and other tcmods would be problematic
11577 // without punting it entirely to a software path)
11578 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11580 amplitude = rsurface.texture->tcmods[0].parms[1];
11581 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
11582 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11583 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11584 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11585 for (j = 0;j < batchnumvertices;j++)
11587 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);
11588 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
11592 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11594 // convert the modified arrays to vertex structs
11595 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
11596 // rsurface.batchvertexmeshbuffer = NULL;
11597 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
11598 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11599 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
11600 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
11601 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11602 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
11603 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
11605 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11607 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
11608 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
11611 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
11612 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11613 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
11614 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
11615 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11616 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
11617 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
11618 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11619 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
11623 void RSurf_DrawBatch(void)
11625 // sometimes a zero triangle surface (usually a degenerate patch) makes it
11626 // through the pipeline, killing it earlier in the pipeline would have
11627 // per-surface overhead rather than per-batch overhead, so it's best to
11628 // reject it here, before it hits glDraw.
11629 if (rsurface.batchnumtriangles == 0)
11632 // batch debugging code
11633 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
11639 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
11640 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
11643 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
11645 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
11647 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
11648 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);
11655 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);
11658 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
11660 // pick the closest matching water plane
11661 int planeindex, vertexindex, bestplaneindex = -1;
11665 r_waterstate_waterplane_t *p;
11666 qboolean prepared = false;
11668 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
11670 if(p->camera_entity != rsurface.texture->camera_entity)
11675 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11677 if(rsurface.batchnumvertices == 0)
11680 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
11682 Matrix4x4_Transform(&rsurface.matrix, v, vert);
11683 d += fabs(PlaneDiff(vert, &p->plane));
11685 if (bestd > d || bestplaneindex < 0)
11688 bestplaneindex = planeindex;
11691 return bestplaneindex;
11692 // NOTE: this MAY return a totally unrelated water plane; we can ignore
11693 // this situation though, as it might be better to render single larger
11694 // batches with useless stuff (backface culled for example) than to
11695 // render multiple smaller batches
11698 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
11701 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11702 rsurface.passcolor4f_vertexbuffer = 0;
11703 rsurface.passcolor4f_bufferoffset = 0;
11704 for (i = 0;i < rsurface.batchnumvertices;i++)
11705 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
11708 static void RSurf_DrawBatch_GL11_ApplyFog(void)
11715 if (rsurface.passcolor4f)
11717 // generate color arrays
11718 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11719 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11720 rsurface.passcolor4f_vertexbuffer = 0;
11721 rsurface.passcolor4f_bufferoffset = 0;
11722 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)
11724 f = RSurf_FogVertex(v);
11733 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11734 rsurface.passcolor4f_vertexbuffer = 0;
11735 rsurface.passcolor4f_bufferoffset = 0;
11736 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
11738 f = RSurf_FogVertex(v);
11747 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
11754 if (!rsurface.passcolor4f)
11756 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11757 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11758 rsurface.passcolor4f_vertexbuffer = 0;
11759 rsurface.passcolor4f_bufferoffset = 0;
11760 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)
11762 f = RSurf_FogVertex(v);
11763 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
11764 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
11765 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
11770 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
11775 if (!rsurface.passcolor4f)
11777 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11778 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11779 rsurface.passcolor4f_vertexbuffer = 0;
11780 rsurface.passcolor4f_bufferoffset = 0;
11781 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11790 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
11795 if (!rsurface.passcolor4f)
11797 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11798 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11799 rsurface.passcolor4f_vertexbuffer = 0;
11800 rsurface.passcolor4f_bufferoffset = 0;
11801 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11803 c2[0] = c[0] + r_refdef.scene.ambient;
11804 c2[1] = c[1] + r_refdef.scene.ambient;
11805 c2[2] = c[2] + r_refdef.scene.ambient;
11810 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11813 rsurface.passcolor4f = NULL;
11814 rsurface.passcolor4f_vertexbuffer = 0;
11815 rsurface.passcolor4f_bufferoffset = 0;
11816 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
11817 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11818 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11819 GL_Color(r, g, b, a);
11820 R_Mesh_TexBind(0, rsurface.lightmaptexture);
11824 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11826 // TODO: optimize applyfog && applycolor case
11827 // just apply fog if necessary, and tint the fog color array if necessary
11828 rsurface.passcolor4f = NULL;
11829 rsurface.passcolor4f_vertexbuffer = 0;
11830 rsurface.passcolor4f_bufferoffset = 0;
11831 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
11832 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11833 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11834 GL_Color(r, g, b, a);
11838 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11841 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11842 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11843 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11844 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
11845 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11846 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11847 GL_Color(r, g, b, a);
11851 static void RSurf_DrawBatch_GL11_ClampColor(void)
11856 if (!rsurface.passcolor4f)
11858 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
11860 c2[0] = bound(0.0f, c1[0], 1.0f);
11861 c2[1] = bound(0.0f, c1[1], 1.0f);
11862 c2[2] = bound(0.0f, c1[2], 1.0f);
11863 c2[3] = bound(0.0f, c1[3], 1.0f);
11867 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
11877 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11878 rsurface.passcolor4f_vertexbuffer = 0;
11879 rsurface.passcolor4f_bufferoffset = 0;
11880 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)
11882 f = -DotProduct(r_refdef.view.forward, n);
11884 f = f * 0.85 + 0.15; // work around so stuff won't get black
11885 f *= r_refdef.lightmapintensity;
11886 Vector4Set(c, f, f, f, 1);
11890 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11892 RSurf_DrawBatch_GL11_ApplyFakeLight();
11893 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
11894 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11895 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11896 GL_Color(r, g, b, a);
11900 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
11908 vec3_t ambientcolor;
11909 vec3_t diffusecolor;
11913 VectorCopy(rsurface.modellight_lightdir, lightdir);
11914 f = 0.5f * r_refdef.lightmapintensity;
11915 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
11916 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
11917 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
11918 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
11919 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
11920 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
11922 if (VectorLength2(diffusecolor) > 0)
11924 // q3-style directional shading
11925 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11926 rsurface.passcolor4f_vertexbuffer = 0;
11927 rsurface.passcolor4f_bufferoffset = 0;
11928 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)
11930 if ((f = DotProduct(n, lightdir)) > 0)
11931 VectorMA(ambientcolor, f, diffusecolor, c);
11933 VectorCopy(ambientcolor, c);
11940 *applycolor = false;
11944 *r = ambientcolor[0];
11945 *g = ambientcolor[1];
11946 *b = ambientcolor[2];
11947 rsurface.passcolor4f = NULL;
11948 rsurface.passcolor4f_vertexbuffer = 0;
11949 rsurface.passcolor4f_bufferoffset = 0;
11953 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11955 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
11956 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
11957 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11958 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11959 GL_Color(r, g, b, a);
11963 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
11969 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
11971 f = 1 - RSurf_FogVertex(v);
11979 void RSurf_SetupDepthAndCulling(void)
11981 // submodels are biased to avoid z-fighting with world surfaces that they
11982 // may be exactly overlapping (avoids z-fighting artifacts on certain
11983 // doors and things in Quake maps)
11984 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
11985 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
11986 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
11987 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11990 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11992 // transparent sky would be ridiculous
11993 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11995 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11996 skyrenderlater = true;
11997 RSurf_SetupDepthAndCulling();
11998 GL_DepthMask(true);
11999 // LordHavoc: HalfLife maps have freaky skypolys so don't use
12000 // skymasking on them, and Quake3 never did sky masking (unlike
12001 // software Quake and software Quake2), so disable the sky masking
12002 // in Quake3 maps as it causes problems with q3map2 sky tricks,
12003 // and skymasking also looks very bad when noclipping outside the
12004 // level, so don't use it then either.
12005 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12007 R_Mesh_ResetTextureState();
12008 if (skyrendermasked)
12010 R_SetupShader_DepthOrShadow();
12011 // depth-only (masking)
12012 GL_ColorMask(0,0,0,0);
12013 // just to make sure that braindead drivers don't draw
12014 // anything despite that colormask...
12015 GL_BlendFunc(GL_ZERO, GL_ONE);
12016 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12017 if (rsurface.batchvertex3fbuffer)
12018 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12020 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12024 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12026 GL_BlendFunc(GL_ONE, GL_ZERO);
12027 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12028 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12029 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12032 if (skyrendermasked)
12033 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12035 R_Mesh_ResetTextureState();
12036 GL_Color(1, 1, 1, 1);
12039 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12040 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12041 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12043 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12047 // render screenspace normalmap to texture
12048 GL_DepthMask(true);
12049 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12054 // bind lightmap texture
12056 // water/refraction/reflection/camera surfaces have to be handled specially
12057 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
12059 int start, end, startplaneindex;
12060 for (start = 0;start < texturenumsurfaces;start = end)
12062 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12063 if(startplaneindex < 0)
12065 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
12066 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
12070 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12072 // now that we have a batch using the same planeindex, render it
12073 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
12075 // render water or distortion background
12076 GL_DepthMask(true);
12077 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));
12079 // blend surface on top
12080 GL_DepthMask(false);
12081 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12084 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
12086 // render surface with reflection texture as input
12087 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12088 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));
12095 // render surface batch normally
12096 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12097 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12101 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12103 // OpenGL 1.3 path - anything not completely ancient
12104 qboolean applycolor;
12107 const texturelayer_t *layer;
12108 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);
12109 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12111 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12114 int layertexrgbscale;
12115 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12117 if (layerindex == 0)
12118 GL_AlphaTest(true);
12121 GL_AlphaTest(false);
12122 GL_DepthFunc(GL_EQUAL);
12125 GL_DepthMask(layer->depthmask && writedepth);
12126 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12127 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12129 layertexrgbscale = 4;
12130 VectorScale(layer->color, 0.25f, layercolor);
12132 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12134 layertexrgbscale = 2;
12135 VectorScale(layer->color, 0.5f, layercolor);
12139 layertexrgbscale = 1;
12140 VectorScale(layer->color, 1.0f, layercolor);
12142 layercolor[3] = layer->color[3];
12143 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12144 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12145 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12146 switch (layer->type)
12148 case TEXTURELAYERTYPE_LITTEXTURE:
12149 // single-pass lightmapped texture with 2x rgbscale
12150 R_Mesh_TexBind(0, r_texture_white);
12151 R_Mesh_TexMatrix(0, NULL);
12152 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12153 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12154 R_Mesh_TexBind(1, layer->texture);
12155 R_Mesh_TexMatrix(1, &layer->texmatrix);
12156 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12157 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12158 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12159 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12160 else if (FAKELIGHT_ENABLED)
12161 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12162 else if (rsurface.uselightmaptexture)
12163 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12165 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12167 case TEXTURELAYERTYPE_TEXTURE:
12168 // singletexture unlit texture with transparency support
12169 R_Mesh_TexBind(0, layer->texture);
12170 R_Mesh_TexMatrix(0, &layer->texmatrix);
12171 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12172 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12173 R_Mesh_TexBind(1, 0);
12174 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12175 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12177 case TEXTURELAYERTYPE_FOG:
12178 // singletexture fogging
12179 if (layer->texture)
12181 R_Mesh_TexBind(0, layer->texture);
12182 R_Mesh_TexMatrix(0, &layer->texmatrix);
12183 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12184 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12188 R_Mesh_TexBind(0, 0);
12189 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12191 R_Mesh_TexBind(1, 0);
12192 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12193 // generate a color array for the fog pass
12194 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12195 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12199 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12202 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12204 GL_DepthFunc(GL_LEQUAL);
12205 GL_AlphaTest(false);
12209 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12211 // OpenGL 1.1 - crusty old voodoo path
12214 const texturelayer_t *layer;
12215 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);
12216 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12218 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12220 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12222 if (layerindex == 0)
12223 GL_AlphaTest(true);
12226 GL_AlphaTest(false);
12227 GL_DepthFunc(GL_EQUAL);
12230 GL_DepthMask(layer->depthmask && writedepth);
12231 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12232 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12233 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12234 switch (layer->type)
12236 case TEXTURELAYERTYPE_LITTEXTURE:
12237 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12239 // two-pass lit texture with 2x rgbscale
12240 // first the lightmap pass
12241 R_Mesh_TexBind(0, r_texture_white);
12242 R_Mesh_TexMatrix(0, NULL);
12243 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12244 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12245 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12246 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12247 else if (FAKELIGHT_ENABLED)
12248 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12249 else if (rsurface.uselightmaptexture)
12250 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12252 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12253 // then apply the texture to it
12254 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12255 R_Mesh_TexBind(0, layer->texture);
12256 R_Mesh_TexMatrix(0, &layer->texmatrix);
12257 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12258 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12259 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);
12263 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12264 R_Mesh_TexBind(0, layer->texture);
12265 R_Mesh_TexMatrix(0, &layer->texmatrix);
12266 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12267 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12268 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12269 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);
12271 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);
12274 case TEXTURELAYERTYPE_TEXTURE:
12275 // singletexture unlit texture with transparency support
12276 R_Mesh_TexBind(0, layer->texture);
12277 R_Mesh_TexMatrix(0, &layer->texmatrix);
12278 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12279 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12280 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);
12282 case TEXTURELAYERTYPE_FOG:
12283 // singletexture fogging
12284 if (layer->texture)
12286 R_Mesh_TexBind(0, layer->texture);
12287 R_Mesh_TexMatrix(0, &layer->texmatrix);
12288 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12289 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12293 R_Mesh_TexBind(0, 0);
12294 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12296 // generate a color array for the fog pass
12297 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12298 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12302 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12305 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12307 GL_DepthFunc(GL_LEQUAL);
12308 GL_AlphaTest(false);
12312 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12316 r_vertexgeneric_t *batchvertex;
12319 // R_Mesh_ResetTextureState();
12320 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12322 if(rsurface.texture && rsurface.texture->currentskinframe)
12324 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12325 c[3] *= rsurface.texture->currentalpha;
12335 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12337 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12338 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12339 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12342 // brighten it up (as texture value 127 means "unlit")
12343 c[0] *= 2 * r_refdef.view.colorscale;
12344 c[1] *= 2 * r_refdef.view.colorscale;
12345 c[2] *= 2 * r_refdef.view.colorscale;
12347 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12348 c[3] *= r_wateralpha.value;
12350 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12352 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12353 GL_DepthMask(false);
12355 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12357 GL_BlendFunc(GL_ONE, GL_ONE);
12358 GL_DepthMask(false);
12360 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12362 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12363 GL_DepthMask(false);
12365 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12367 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12368 GL_DepthMask(false);
12372 GL_BlendFunc(GL_ONE, GL_ZERO);
12373 GL_DepthMask(writedepth);
12376 if (r_showsurfaces.integer == 3)
12378 rsurface.passcolor4f = NULL;
12380 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12382 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12384 rsurface.passcolor4f = NULL;
12385 rsurface.passcolor4f_vertexbuffer = 0;
12386 rsurface.passcolor4f_bufferoffset = 0;
12388 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12390 qboolean applycolor = true;
12393 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12395 r_refdef.lightmapintensity = 1;
12396 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12397 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12399 else if (FAKELIGHT_ENABLED)
12401 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12403 r_refdef.lightmapintensity = r_fakelight_intensity.value;
12404 RSurf_DrawBatch_GL11_ApplyFakeLight();
12405 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12409 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12411 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12412 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12413 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12416 if(!rsurface.passcolor4f)
12417 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12419 RSurf_DrawBatch_GL11_ApplyAmbient();
12420 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12421 if(r_refdef.fogenabled)
12422 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12423 RSurf_DrawBatch_GL11_ClampColor();
12425 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12426 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12429 else if (!r_refdef.view.showdebug)
12431 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12432 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12433 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12435 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12436 Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12438 R_Mesh_PrepareVertices_Generic_Unlock();
12441 else if (r_showsurfaces.integer == 4)
12443 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12444 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12445 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12447 unsigned char c = vi << 3;
12448 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12449 Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12451 R_Mesh_PrepareVertices_Generic_Unlock();
12454 else if (r_showsurfaces.integer == 2)
12457 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12458 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12459 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12461 unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12462 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12463 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12464 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12465 Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12466 Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12467 Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12469 R_Mesh_PrepareVertices_Generic_Unlock();
12470 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12474 int texturesurfaceindex;
12476 const msurface_t *surface;
12477 unsigned char surfacecolor4ub[4];
12478 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12479 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12481 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12483 surface = texturesurfacelist[texturesurfaceindex];
12484 k = (int)(((size_t)surface) / sizeof(msurface_t));
12485 Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
12486 for (j = 0;j < surface->num_vertices;j++)
12488 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12489 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
12493 R_Mesh_PrepareVertices_Generic_Unlock();
12498 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12501 RSurf_SetupDepthAndCulling();
12502 if (r_showsurfaces.integer)
12504 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12507 switch (vid.renderpath)
12509 case RENDERPATH_GL20:
12510 case RENDERPATH_D3D9:
12511 case RENDERPATH_D3D10:
12512 case RENDERPATH_D3D11:
12513 case RENDERPATH_SOFT:
12514 case RENDERPATH_GLES2:
12515 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12517 case RENDERPATH_GL13:
12518 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12520 case RENDERPATH_GL11:
12521 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12527 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12530 RSurf_SetupDepthAndCulling();
12531 if (r_showsurfaces.integer)
12533 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12536 switch (vid.renderpath)
12538 case RENDERPATH_GL20:
12539 case RENDERPATH_D3D9:
12540 case RENDERPATH_D3D10:
12541 case RENDERPATH_D3D11:
12542 case RENDERPATH_SOFT:
12543 case RENDERPATH_GLES2:
12544 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12546 case RENDERPATH_GL13:
12547 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12549 case RENDERPATH_GL11:
12550 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12556 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12559 int texturenumsurfaces, endsurface;
12560 texture_t *texture;
12561 const msurface_t *surface;
12562 #define MAXBATCH_TRANSPARENTSURFACES 256
12563 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
12565 // if the model is static it doesn't matter what value we give for
12566 // wantnormals and wanttangents, so this logic uses only rules applicable
12567 // to a model, knowing that they are meaningless otherwise
12568 if (ent == r_refdef.scene.worldentity)
12569 RSurf_ActiveWorldEntity();
12570 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12571 RSurf_ActiveModelEntity(ent, false, false, false);
12574 switch (vid.renderpath)
12576 case RENDERPATH_GL20:
12577 case RENDERPATH_D3D9:
12578 case RENDERPATH_D3D10:
12579 case RENDERPATH_D3D11:
12580 case RENDERPATH_SOFT:
12581 case RENDERPATH_GLES2:
12582 RSurf_ActiveModelEntity(ent, true, true, false);
12584 case RENDERPATH_GL13:
12585 case RENDERPATH_GL11:
12586 RSurf_ActiveModelEntity(ent, true, false, false);
12591 if (r_transparentdepthmasking.integer)
12593 qboolean setup = false;
12594 for (i = 0;i < numsurfaces;i = j)
12597 surface = rsurface.modelsurfaces + surfacelist[i];
12598 texture = surface->texture;
12599 rsurface.texture = R_GetCurrentTexture(texture);
12600 rsurface.lightmaptexture = NULL;
12601 rsurface.deluxemaptexture = NULL;
12602 rsurface.uselightmaptexture = false;
12603 // scan ahead until we find a different texture
12604 endsurface = min(i + 1024, numsurfaces);
12605 texturenumsurfaces = 0;
12606 texturesurfacelist[texturenumsurfaces++] = surface;
12607 for (;j < endsurface;j++)
12609 surface = rsurface.modelsurfaces + surfacelist[j];
12610 if (texture != surface->texture)
12612 texturesurfacelist[texturenumsurfaces++] = surface;
12614 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
12616 // render the range of surfaces as depth
12620 GL_ColorMask(0,0,0,0);
12622 GL_DepthTest(true);
12623 GL_BlendFunc(GL_ONE, GL_ZERO);
12624 GL_DepthMask(true);
12625 // R_Mesh_ResetTextureState();
12626 R_SetupShader_DepthOrShadow();
12628 RSurf_SetupDepthAndCulling();
12629 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
12630 if (rsurface.batchvertex3fbuffer)
12631 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12633 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12637 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12640 for (i = 0;i < numsurfaces;i = j)
12643 surface = rsurface.modelsurfaces + surfacelist[i];
12644 texture = surface->texture;
12645 rsurface.texture = R_GetCurrentTexture(texture);
12646 // scan ahead until we find a different texture
12647 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
12648 texturenumsurfaces = 0;
12649 texturesurfacelist[texturenumsurfaces++] = surface;
12650 if(FAKELIGHT_ENABLED)
12652 rsurface.lightmaptexture = NULL;
12653 rsurface.deluxemaptexture = NULL;
12654 rsurface.uselightmaptexture = false;
12655 for (;j < endsurface;j++)
12657 surface = rsurface.modelsurfaces + surfacelist[j];
12658 if (texture != surface->texture)
12660 texturesurfacelist[texturenumsurfaces++] = surface;
12665 rsurface.lightmaptexture = surface->lightmaptexture;
12666 rsurface.deluxemaptexture = surface->deluxemaptexture;
12667 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
12668 for (;j < endsurface;j++)
12670 surface = rsurface.modelsurfaces + surfacelist[j];
12671 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
12673 texturesurfacelist[texturenumsurfaces++] = surface;
12676 // render the range of surfaces
12677 if (ent == r_refdef.scene.worldentity)
12678 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12680 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12682 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12685 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
12687 // transparent surfaces get pushed off into the transparent queue
12688 int surfacelistindex;
12689 const msurface_t *surface;
12690 vec3_t tempcenter, center;
12691 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
12693 surface = texturesurfacelist[surfacelistindex];
12694 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
12695 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
12696 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
12697 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
12698 if (queueentity->transparent_offset) // transparent offset
12700 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
12701 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
12702 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
12704 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
12708 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12710 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
12712 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
12714 RSurf_SetupDepthAndCulling();
12715 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
12716 if (rsurface.batchvertex3fbuffer)
12717 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12719 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12723 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
12725 const entity_render_t *queueentity = r_refdef.scene.worldentity;
12728 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12731 if (!rsurface.texture->currentnumlayers)
12733 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12734 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12736 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12738 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12739 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12740 else if (!rsurface.texture->currentnumlayers)
12742 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12744 // in the deferred case, transparent surfaces were queued during prepass
12745 if (!r_shadow_usingdeferredprepass)
12746 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12750 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12751 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12756 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12759 texture_t *texture;
12760 R_FrameData_SetMark();
12761 // break the surface list down into batches by texture and use of lightmapping
12762 for (i = 0;i < numsurfaces;i = j)
12765 // texture is the base texture pointer, rsurface.texture is the
12766 // current frame/skin the texture is directing us to use (for example
12767 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12768 // use skin 1 instead)
12769 texture = surfacelist[i]->texture;
12770 rsurface.texture = R_GetCurrentTexture(texture);
12771 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12773 // if this texture is not the kind we want, skip ahead to the next one
12774 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12778 if(FAKELIGHT_ENABLED || depthonly || prepass)
12780 rsurface.lightmaptexture = NULL;
12781 rsurface.deluxemaptexture = NULL;
12782 rsurface.uselightmaptexture = false;
12783 // simply scan ahead until we find a different texture or lightmap state
12784 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12789 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12790 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12791 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
12792 // simply scan ahead until we find a different texture or lightmap state
12793 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12796 // render the range of surfaces
12797 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
12799 R_FrameData_ReturnToMark();
12802 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
12806 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12809 if (!rsurface.texture->currentnumlayers)
12811 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12812 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12814 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12816 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12817 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12818 else if (!rsurface.texture->currentnumlayers)
12820 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12822 // in the deferred case, transparent surfaces were queued during prepass
12823 if (!r_shadow_usingdeferredprepass)
12824 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12828 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12829 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12834 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12837 texture_t *texture;
12838 R_FrameData_SetMark();
12839 // break the surface list down into batches by texture and use of lightmapping
12840 for (i = 0;i < numsurfaces;i = j)
12843 // texture is the base texture pointer, rsurface.texture is the
12844 // current frame/skin the texture is directing us to use (for example
12845 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12846 // use skin 1 instead)
12847 texture = surfacelist[i]->texture;
12848 rsurface.texture = R_GetCurrentTexture(texture);
12849 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12851 // if this texture is not the kind we want, skip ahead to the next one
12852 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12856 if(FAKELIGHT_ENABLED || depthonly || prepass)
12858 rsurface.lightmaptexture = NULL;
12859 rsurface.deluxemaptexture = NULL;
12860 rsurface.uselightmaptexture = false;
12861 // simply scan ahead until we find a different texture or lightmap state
12862 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12867 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12868 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12869 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
12870 // simply scan ahead until we find a different texture or lightmap state
12871 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12874 // render the range of surfaces
12875 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
12877 R_FrameData_ReturnToMark();
12880 float locboxvertex3f[6*4*3] =
12882 1,0,1, 1,0,0, 1,1,0, 1,1,1,
12883 0,1,1, 0,1,0, 0,0,0, 0,0,1,
12884 1,1,1, 1,1,0, 0,1,0, 0,1,1,
12885 0,0,1, 0,0,0, 1,0,0, 1,0,1,
12886 0,0,1, 1,0,1, 1,1,1, 0,1,1,
12887 1,0,0, 0,0,0, 0,1,0, 1,1,0
12890 unsigned short locboxelements[6*2*3] =
12895 12,13,14, 12,14,15,
12896 16,17,18, 16,18,19,
12900 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12903 cl_locnode_t *loc = (cl_locnode_t *)ent;
12905 float vertex3f[6*4*3];
12907 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12908 GL_DepthMask(false);
12909 GL_DepthRange(0, 1);
12910 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12911 GL_DepthTest(true);
12912 GL_CullFace(GL_NONE);
12913 R_EntityMatrix(&identitymatrix);
12915 // R_Mesh_ResetTextureState();
12917 i = surfacelist[0];
12918 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12919 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12920 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12921 surfacelist[0] < 0 ? 0.5f : 0.125f);
12923 if (VectorCompare(loc->mins, loc->maxs))
12925 VectorSet(size, 2, 2, 2);
12926 VectorMA(loc->mins, -0.5f, size, mins);
12930 VectorCopy(loc->mins, mins);
12931 VectorSubtract(loc->maxs, loc->mins, size);
12934 for (i = 0;i < 6*4*3;)
12935 for (j = 0;j < 3;j++, i++)
12936 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
12938 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
12939 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12940 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
12943 void R_DrawLocs(void)
12946 cl_locnode_t *loc, *nearestloc;
12948 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
12949 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
12951 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
12952 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
12956 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
12958 if (decalsystem->decals)
12959 Mem_Free(decalsystem->decals);
12960 memset(decalsystem, 0, sizeof(*decalsystem));
12963 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)
12966 tridecal_t *decals;
12969 // expand or initialize the system
12970 if (decalsystem->maxdecals <= decalsystem->numdecals)
12972 decalsystem_t old = *decalsystem;
12973 qboolean useshortelements;
12974 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
12975 useshortelements = decalsystem->maxdecals * 3 <= 65536;
12976 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)));
12977 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
12978 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
12979 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
12980 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
12981 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
12982 if (decalsystem->numdecals)
12983 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
12985 Mem_Free(old.decals);
12986 for (i = 0;i < decalsystem->maxdecals*3;i++)
12987 decalsystem->element3i[i] = i;
12988 if (useshortelements)
12989 for (i = 0;i < decalsystem->maxdecals*3;i++)
12990 decalsystem->element3s[i] = i;
12993 // grab a decal and search for another free slot for the next one
12994 decals = decalsystem->decals;
12995 decal = decalsystem->decals + (i = decalsystem->freedecal++);
12996 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
12998 decalsystem->freedecal = i;
12999 if (decalsystem->numdecals <= i)
13000 decalsystem->numdecals = i + 1;
13002 // initialize the decal
13004 decal->triangleindex = triangleindex;
13005 decal->surfaceindex = surfaceindex;
13006 decal->decalsequence = decalsequence;
13007 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13008 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13009 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13010 decal->color4ub[0][3] = 255;
13011 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13012 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13013 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13014 decal->color4ub[1][3] = 255;
13015 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13016 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13017 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13018 decal->color4ub[2][3] = 255;
13019 decal->vertex3f[0][0] = v0[0];
13020 decal->vertex3f[0][1] = v0[1];
13021 decal->vertex3f[0][2] = v0[2];
13022 decal->vertex3f[1][0] = v1[0];
13023 decal->vertex3f[1][1] = v1[1];
13024 decal->vertex3f[1][2] = v1[2];
13025 decal->vertex3f[2][0] = v2[0];
13026 decal->vertex3f[2][1] = v2[1];
13027 decal->vertex3f[2][2] = v2[2];
13028 decal->texcoord2f[0][0] = t0[0];
13029 decal->texcoord2f[0][1] = t0[1];
13030 decal->texcoord2f[1][0] = t1[0];
13031 decal->texcoord2f[1][1] = t1[1];
13032 decal->texcoord2f[2][0] = t2[0];
13033 decal->texcoord2f[2][1] = t2[1];
13036 extern cvar_t cl_decals_bias;
13037 extern cvar_t cl_decals_models;
13038 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13039 // baseparms, parms, temps
13040 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)
13045 const float *vertex3f;
13047 float points[2][9][3];
13054 e = rsurface.modelelement3i + 3*triangleindex;
13056 vertex3f = rsurface.modelvertex3f;
13058 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13060 index = 3*e[cornerindex];
13061 VectorCopy(vertex3f + index, v[cornerindex]);
13064 //TriangleNormal(v[0], v[1], v[2], normal);
13065 //if (DotProduct(normal, localnormal) < 0.0f)
13067 // clip by each of the box planes formed from the projection matrix
13068 // if anything survives, we emit the decal
13069 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]);
13072 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]);
13075 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]);
13078 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]);
13081 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]);
13084 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]);
13087 // some part of the triangle survived, so we have to accept it...
13090 // dynamic always uses the original triangle
13092 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13094 index = 3*e[cornerindex];
13095 VectorCopy(vertex3f + index, v[cornerindex]);
13098 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13100 // convert vertex positions to texcoords
13101 Matrix4x4_Transform(projection, v[cornerindex], temp);
13102 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13103 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13104 // calculate distance fade from the projection origin
13105 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13106 f = bound(0.0f, f, 1.0f);
13107 c[cornerindex][0] = r * f;
13108 c[cornerindex][1] = g * f;
13109 c[cornerindex][2] = b * f;
13110 c[cornerindex][3] = 1.0f;
13111 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13114 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);
13116 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13117 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);
13119 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)
13121 matrix4x4_t projection;
13122 decalsystem_t *decalsystem;
13125 const msurface_t *surface;
13126 const msurface_t *surfaces;
13127 const int *surfacelist;
13128 const texture_t *texture;
13130 int numsurfacelist;
13131 int surfacelistindex;
13134 float localorigin[3];
13135 float localnormal[3];
13136 float localmins[3];
13137 float localmaxs[3];
13140 float planes[6][4];
13143 int bih_triangles_count;
13144 int bih_triangles[256];
13145 int bih_surfaces[256];
13147 decalsystem = &ent->decalsystem;
13148 model = ent->model;
13149 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13151 R_DecalSystem_Reset(&ent->decalsystem);
13155 if (!model->brush.data_leafs && !cl_decals_models.integer)
13157 if (decalsystem->model)
13158 R_DecalSystem_Reset(decalsystem);
13162 if (decalsystem->model != model)
13163 R_DecalSystem_Reset(decalsystem);
13164 decalsystem->model = model;
13166 RSurf_ActiveModelEntity(ent, false, false, false);
13168 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13169 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13170 VectorNormalize(localnormal);
13171 localsize = worldsize*rsurface.inversematrixscale;
13172 localmins[0] = localorigin[0] - localsize;
13173 localmins[1] = localorigin[1] - localsize;
13174 localmins[2] = localorigin[2] - localsize;
13175 localmaxs[0] = localorigin[0] + localsize;
13176 localmaxs[1] = localorigin[1] + localsize;
13177 localmaxs[2] = localorigin[2] + localsize;
13179 //VectorCopy(localnormal, planes[4]);
13180 //VectorVectors(planes[4], planes[2], planes[0]);
13181 AnglesFromVectors(angles, localnormal, NULL, false);
13182 AngleVectors(angles, planes[0], planes[2], planes[4]);
13183 VectorNegate(planes[0], planes[1]);
13184 VectorNegate(planes[2], planes[3]);
13185 VectorNegate(planes[4], planes[5]);
13186 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13187 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13188 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13189 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13190 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13191 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13196 matrix4x4_t forwardprojection;
13197 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13198 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13203 float projectionvector[4][3];
13204 VectorScale(planes[0], ilocalsize, projectionvector[0]);
13205 VectorScale(planes[2], ilocalsize, projectionvector[1]);
13206 VectorScale(planes[4], ilocalsize, projectionvector[2]);
13207 projectionvector[0][0] = planes[0][0] * ilocalsize;
13208 projectionvector[0][1] = planes[1][0] * ilocalsize;
13209 projectionvector[0][2] = planes[2][0] * ilocalsize;
13210 projectionvector[1][0] = planes[0][1] * ilocalsize;
13211 projectionvector[1][1] = planes[1][1] * ilocalsize;
13212 projectionvector[1][2] = planes[2][1] * ilocalsize;
13213 projectionvector[2][0] = planes[0][2] * ilocalsize;
13214 projectionvector[2][1] = planes[1][2] * ilocalsize;
13215 projectionvector[2][2] = planes[2][2] * ilocalsize;
13216 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13217 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13218 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13219 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13223 dynamic = model->surfmesh.isanimated;
13224 numsurfacelist = model->nummodelsurfaces;
13225 surfacelist = model->sortedmodelsurfaces;
13226 surfaces = model->data_surfaces;
13229 bih_triangles_count = -1;
13232 if(model->render_bih.numleafs)
13233 bih = &model->render_bih;
13234 else if(model->collision_bih.numleafs)
13235 bih = &model->collision_bih;
13238 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13239 if(bih_triangles_count == 0)
13241 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13243 if(bih_triangles_count > 0)
13245 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13247 surfaceindex = bih_surfaces[triangleindex];
13248 surface = surfaces + surfaceindex;
13249 texture = surface->texture;
13250 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13252 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13254 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13259 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13261 surfaceindex = surfacelist[surfacelistindex];
13262 surface = surfaces + surfaceindex;
13263 // check cull box first because it rejects more than any other check
13264 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13266 // skip transparent surfaces
13267 texture = surface->texture;
13268 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13270 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13272 numtriangles = surface->num_triangles;
13273 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13274 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13279 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13280 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)
13282 int renderentityindex;
13283 float worldmins[3];
13284 float worldmaxs[3];
13285 entity_render_t *ent;
13287 if (!cl_decals_newsystem.integer)
13290 worldmins[0] = worldorigin[0] - worldsize;
13291 worldmins[1] = worldorigin[1] - worldsize;
13292 worldmins[2] = worldorigin[2] - worldsize;
13293 worldmaxs[0] = worldorigin[0] + worldsize;
13294 worldmaxs[1] = worldorigin[1] + worldsize;
13295 worldmaxs[2] = worldorigin[2] + worldsize;
13297 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13299 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13301 ent = r_refdef.scene.entities[renderentityindex];
13302 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13305 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13309 typedef struct r_decalsystem_splatqueue_s
13311 vec3_t worldorigin;
13312 vec3_t worldnormal;
13318 r_decalsystem_splatqueue_t;
13320 int r_decalsystem_numqueued = 0;
13321 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13323 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)
13325 r_decalsystem_splatqueue_t *queue;
13327 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13330 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13331 VectorCopy(worldorigin, queue->worldorigin);
13332 VectorCopy(worldnormal, queue->worldnormal);
13333 Vector4Set(queue->color, r, g, b, a);
13334 Vector4Set(queue->tcrange, s1, t1, s2, t2);
13335 queue->worldsize = worldsize;
13336 queue->decalsequence = cl.decalsequence++;
13339 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13342 r_decalsystem_splatqueue_t *queue;
13344 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13345 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);
13346 r_decalsystem_numqueued = 0;
13349 extern cvar_t cl_decals_max;
13350 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13353 decalsystem_t *decalsystem = &ent->decalsystem;
13360 if (!decalsystem->numdecals)
13363 if (r_showsurfaces.integer)
13366 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13368 R_DecalSystem_Reset(decalsystem);
13372 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13373 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13375 if (decalsystem->lastupdatetime)
13376 frametime = (cl.time - decalsystem->lastupdatetime);
13379 decalsystem->lastupdatetime = cl.time;
13380 decal = decalsystem->decals;
13381 numdecals = decalsystem->numdecals;
13383 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13385 if (decal->color4ub[0][3])
13387 decal->lived += frametime;
13388 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13390 memset(decal, 0, sizeof(*decal));
13391 if (decalsystem->freedecal > i)
13392 decalsystem->freedecal = i;
13396 decal = decalsystem->decals;
13397 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13400 // collapse the array by shuffling the tail decals into the gaps
13403 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13404 decalsystem->freedecal++;
13405 if (decalsystem->freedecal == numdecals)
13407 decal[decalsystem->freedecal] = decal[--numdecals];
13410 decalsystem->numdecals = numdecals;
13412 if (numdecals <= 0)
13414 // if there are no decals left, reset decalsystem
13415 R_DecalSystem_Reset(decalsystem);
13419 extern skinframe_t *decalskinframe;
13420 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13423 decalsystem_t *decalsystem = &ent->decalsystem;
13432 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13435 numdecals = decalsystem->numdecals;
13439 if (r_showsurfaces.integer)
13442 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13444 R_DecalSystem_Reset(decalsystem);
13448 // if the model is static it doesn't matter what value we give for
13449 // wantnormals and wanttangents, so this logic uses only rules applicable
13450 // to a model, knowing that they are meaningless otherwise
13451 if (ent == r_refdef.scene.worldentity)
13452 RSurf_ActiveWorldEntity();
13454 RSurf_ActiveModelEntity(ent, false, false, false);
13456 decalsystem->lastupdatetime = cl.time;
13457 decal = decalsystem->decals;
13459 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13461 // update vertex positions for animated models
13462 v3f = decalsystem->vertex3f;
13463 c4f = decalsystem->color4f;
13464 t2f = decalsystem->texcoord2f;
13465 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13467 if (!decal->color4ub[0][3])
13470 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13473 // update color values for fading decals
13474 if (decal->lived >= cl_decals_time.value)
13476 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13477 alpha *= (1.0f/255.0f);
13480 alpha = 1.0f/255.0f;
13482 c4f[ 0] = decal->color4ub[0][0] * alpha;
13483 c4f[ 1] = decal->color4ub[0][1] * alpha;
13484 c4f[ 2] = decal->color4ub[0][2] * alpha;
13486 c4f[ 4] = decal->color4ub[1][0] * alpha;
13487 c4f[ 5] = decal->color4ub[1][1] * alpha;
13488 c4f[ 6] = decal->color4ub[1][2] * alpha;
13490 c4f[ 8] = decal->color4ub[2][0] * alpha;
13491 c4f[ 9] = decal->color4ub[2][1] * alpha;
13492 c4f[10] = decal->color4ub[2][2] * alpha;
13495 t2f[0] = decal->texcoord2f[0][0];
13496 t2f[1] = decal->texcoord2f[0][1];
13497 t2f[2] = decal->texcoord2f[1][0];
13498 t2f[3] = decal->texcoord2f[1][1];
13499 t2f[4] = decal->texcoord2f[2][0];
13500 t2f[5] = decal->texcoord2f[2][1];
13502 // update vertex positions for animated models
13503 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13505 e = rsurface.modelelement3i + 3*decal->triangleindex;
13506 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
13507 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
13508 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
13512 VectorCopy(decal->vertex3f[0], v3f);
13513 VectorCopy(decal->vertex3f[1], v3f + 3);
13514 VectorCopy(decal->vertex3f[2], v3f + 6);
13517 if (r_refdef.fogenabled)
13519 alpha = RSurf_FogVertex(v3f);
13520 VectorScale(c4f, alpha, c4f);
13521 alpha = RSurf_FogVertex(v3f + 3);
13522 VectorScale(c4f + 4, alpha, c4f + 4);
13523 alpha = RSurf_FogVertex(v3f + 6);
13524 VectorScale(c4f + 8, alpha, c4f + 8);
13535 r_refdef.stats.drawndecals += numtris;
13537 // now render the decals all at once
13538 // (this assumes they all use one particle font texture!)
13539 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);
13540 // R_Mesh_ResetTextureState();
13541 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
13542 GL_DepthMask(false);
13543 GL_DepthRange(0, 1);
13544 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
13545 GL_DepthTest(true);
13546 GL_CullFace(GL_NONE);
13547 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
13548 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
13549 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
13553 static void R_DrawModelDecals(void)
13557 // fade faster when there are too many decals
13558 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13559 for (i = 0;i < r_refdef.scene.numentities;i++)
13560 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13562 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
13563 for (i = 0;i < r_refdef.scene.numentities;i++)
13564 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13565 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
13567 R_DecalSystem_ApplySplatEntitiesQueue();
13569 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13570 for (i = 0;i < r_refdef.scene.numentities;i++)
13571 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13573 r_refdef.stats.totaldecals += numdecals;
13575 if (r_showsurfaces.integer)
13578 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
13580 for (i = 0;i < r_refdef.scene.numentities;i++)
13582 if (!r_refdef.viewcache.entityvisible[i])
13584 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13585 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
13589 extern cvar_t mod_collision_bih;
13590 void R_DrawDebugModel(void)
13592 entity_render_t *ent = rsurface.entity;
13593 int i, j, k, l, flagsmask;
13594 const msurface_t *surface;
13595 dp_model_t *model = ent->model;
13598 switch(vid.renderpath)
13600 case RENDERPATH_GL11:
13601 case RENDERPATH_GL13:
13602 case RENDERPATH_GL20:
13604 case RENDERPATH_D3D9:
13605 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13607 case RENDERPATH_D3D10:
13608 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13610 case RENDERPATH_D3D11:
13611 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13613 case RENDERPATH_SOFT:
13614 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13616 case RENDERPATH_GLES2:
13617 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13621 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
13623 // R_Mesh_ResetTextureState();
13624 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13625 GL_DepthRange(0, 1);
13626 GL_DepthTest(!r_showdisabledepthtest.integer);
13627 GL_DepthMask(false);
13628 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13630 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
13634 qboolean cullbox = ent == r_refdef.scene.worldentity;
13635 const q3mbrush_t *brush;
13636 const bih_t *bih = &model->collision_bih;
13637 const bih_leaf_t *bihleaf;
13638 float vertex3f[3][3];
13639 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
13641 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
13643 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
13645 switch (bihleaf->type)
13648 brush = model->brush.data_brushes + bihleaf->itemindex;
13649 if (brush->colbrushf && brush->colbrushf->numtriangles)
13651 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);
13652 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
13653 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
13656 case BIH_COLLISIONTRIANGLE:
13657 triangleindex = bihleaf->itemindex;
13658 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
13659 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
13660 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
13661 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);
13662 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13663 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13665 case BIH_RENDERTRIANGLE:
13666 triangleindex = bihleaf->itemindex;
13667 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
13668 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
13669 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
13670 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);
13671 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13672 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13678 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13680 if (r_showtris.integer || (r_shownormals.value != 0))
13682 if (r_showdisabledepthtest.integer)
13684 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13685 GL_DepthMask(false);
13689 GL_BlendFunc(GL_ONE, GL_ZERO);
13690 GL_DepthMask(true);
13692 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
13694 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
13696 rsurface.texture = R_GetCurrentTexture(surface->texture);
13697 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
13699 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
13700 if (r_showtris.value > 0)
13702 if (!rsurface.texture->currentlayers->depthmask)
13703 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
13704 else if (ent == r_refdef.scene.worldentity)
13705 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
13707 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
13708 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
13709 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
13711 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
13714 if (r_shownormals.value < 0)
13716 qglBegin(GL_LINES);
13717 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13719 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13720 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13721 qglVertex3f(v[0], v[1], v[2]);
13722 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
13723 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13724 qglVertex3f(v[0], v[1], v[2]);
13729 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
13731 qglBegin(GL_LINES);
13732 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13734 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13735 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13736 qglVertex3f(v[0], v[1], v[2]);
13737 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
13738 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13739 qglVertex3f(v[0], v[1], v[2]);
13743 qglBegin(GL_LINES);
13744 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13746 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13747 GL_Color(0, r_refdef.view.colorscale, 0, 1);
13748 qglVertex3f(v[0], v[1], v[2]);
13749 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
13750 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13751 qglVertex3f(v[0], v[1], v[2]);
13755 qglBegin(GL_LINES);
13756 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13758 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13759 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13760 qglVertex3f(v[0], v[1], v[2]);
13761 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
13762 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13763 qglVertex3f(v[0], v[1], v[2]);
13770 rsurface.texture = NULL;
13774 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
13775 int r_maxsurfacelist = 0;
13776 const msurface_t **r_surfacelist = NULL;
13777 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13779 int i, j, endj, flagsmask;
13780 dp_model_t *model = r_refdef.scene.worldmodel;
13781 msurface_t *surfaces;
13782 unsigned char *update;
13783 int numsurfacelist = 0;
13787 if (r_maxsurfacelist < model->num_surfaces)
13789 r_maxsurfacelist = model->num_surfaces;
13791 Mem_Free((msurface_t**)r_surfacelist);
13792 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13795 RSurf_ActiveWorldEntity();
13797 surfaces = model->data_surfaces;
13798 update = model->brushq1.lightmapupdateflags;
13800 // update light styles on this submodel
13801 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13803 model_brush_lightstyleinfo_t *style;
13804 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13806 if (style->value != r_refdef.scene.lightstylevalue[style->style])
13808 int *list = style->surfacelist;
13809 style->value = r_refdef.scene.lightstylevalue[style->style];
13810 for (j = 0;j < style->numsurfaces;j++)
13811 update[list[j]] = true;
13816 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13820 R_DrawDebugModel();
13821 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13825 rsurface.lightmaptexture = NULL;
13826 rsurface.deluxemaptexture = NULL;
13827 rsurface.uselightmaptexture = false;
13828 rsurface.texture = NULL;
13829 rsurface.rtlight = NULL;
13830 numsurfacelist = 0;
13831 // add visible surfaces to draw list
13832 for (i = 0;i < model->nummodelsurfaces;i++)
13834 j = model->sortedmodelsurfaces[i];
13835 if (r_refdef.viewcache.world_surfacevisible[j])
13836 r_surfacelist[numsurfacelist++] = surfaces + j;
13838 // update lightmaps if needed
13839 if (model->brushq1.firstrender)
13841 model->brushq1.firstrender = false;
13842 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13844 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13848 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13849 if (r_refdef.viewcache.world_surfacevisible[j])
13851 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13853 // don't do anything if there were no surfaces
13854 if (!numsurfacelist)
13856 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13859 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13861 // add to stats if desired
13862 if (r_speeds.integer && !skysurfaces && !depthonly)
13864 r_refdef.stats.world_surfaces += numsurfacelist;
13865 for (j = 0;j < numsurfacelist;j++)
13866 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
13869 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13872 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13874 int i, j, endj, flagsmask;
13875 dp_model_t *model = ent->model;
13876 msurface_t *surfaces;
13877 unsigned char *update;
13878 int numsurfacelist = 0;
13882 if (r_maxsurfacelist < model->num_surfaces)
13884 r_maxsurfacelist = model->num_surfaces;
13886 Mem_Free((msurface_t **)r_surfacelist);
13887 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13890 // if the model is static it doesn't matter what value we give for
13891 // wantnormals and wanttangents, so this logic uses only rules applicable
13892 // to a model, knowing that they are meaningless otherwise
13893 if (ent == r_refdef.scene.worldentity)
13894 RSurf_ActiveWorldEntity();
13895 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13896 RSurf_ActiveModelEntity(ent, false, false, false);
13898 RSurf_ActiveModelEntity(ent, true, true, true);
13899 else if (depthonly)
13901 switch (vid.renderpath)
13903 case RENDERPATH_GL20:
13904 case RENDERPATH_D3D9:
13905 case RENDERPATH_D3D10:
13906 case RENDERPATH_D3D11:
13907 case RENDERPATH_SOFT:
13908 case RENDERPATH_GLES2:
13909 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
13911 case RENDERPATH_GL13:
13912 case RENDERPATH_GL11:
13913 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
13919 switch (vid.renderpath)
13921 case RENDERPATH_GL20:
13922 case RENDERPATH_D3D9:
13923 case RENDERPATH_D3D10:
13924 case RENDERPATH_D3D11:
13925 case RENDERPATH_SOFT:
13926 case RENDERPATH_GLES2:
13927 RSurf_ActiveModelEntity(ent, true, true, false);
13929 case RENDERPATH_GL13:
13930 case RENDERPATH_GL11:
13931 RSurf_ActiveModelEntity(ent, true, false, false);
13936 surfaces = model->data_surfaces;
13937 update = model->brushq1.lightmapupdateflags;
13939 // update light styles
13940 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13942 model_brush_lightstyleinfo_t *style;
13943 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13945 if (style->value != r_refdef.scene.lightstylevalue[style->style])
13947 int *list = style->surfacelist;
13948 style->value = r_refdef.scene.lightstylevalue[style->style];
13949 for (j = 0;j < style->numsurfaces;j++)
13950 update[list[j]] = true;
13955 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13959 R_DrawDebugModel();
13960 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13964 rsurface.lightmaptexture = NULL;
13965 rsurface.deluxemaptexture = NULL;
13966 rsurface.uselightmaptexture = false;
13967 rsurface.texture = NULL;
13968 rsurface.rtlight = NULL;
13969 numsurfacelist = 0;
13970 // add visible surfaces to draw list
13971 for (i = 0;i < model->nummodelsurfaces;i++)
13972 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
13973 // don't do anything if there were no surfaces
13974 if (!numsurfacelist)
13976 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13979 // update lightmaps if needed
13983 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13988 R_BuildLightMap(ent, surfaces + j);
13993 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13995 R_BuildLightMap(ent, surfaces + j);
13996 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13998 // add to stats if desired
13999 if (r_speeds.integer && !skysurfaces && !depthonly)
14001 r_refdef.stats.entities_surfaces += numsurfacelist;
14002 for (j = 0;j < numsurfacelist;j++)
14003 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14006 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14009 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14011 static texture_t texture;
14012 static msurface_t surface;
14013 const msurface_t *surfacelist = &surface;
14015 // fake enough texture and surface state to render this geometry
14017 texture.update_lastrenderframe = -1; // regenerate this texture
14018 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14019 texture.currentskinframe = skinframe;
14020 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14021 texture.offsetmapping = OFFSETMAPPING_OFF;
14022 texture.offsetscale = 1;
14023 texture.specularscalemod = 1;
14024 texture.specularpowermod = 1;
14026 surface.texture = &texture;
14027 surface.num_triangles = numtriangles;
14028 surface.num_firsttriangle = firsttriangle;
14029 surface.num_vertices = numvertices;
14030 surface.num_firstvertex = firstvertex;
14033 rsurface.texture = R_GetCurrentTexture(surface.texture);
14034 rsurface.lightmaptexture = NULL;
14035 rsurface.deluxemaptexture = NULL;
14036 rsurface.uselightmaptexture = false;
14037 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14040 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)
14042 static msurface_t surface;
14043 const msurface_t *surfacelist = &surface;
14045 // fake enough texture and surface state to render this geometry
14046 surface.texture = texture;
14047 surface.num_triangles = numtriangles;
14048 surface.num_firsttriangle = firsttriangle;
14049 surface.num_vertices = numvertices;
14050 surface.num_firstvertex = firstvertex;
14053 rsurface.texture = R_GetCurrentTexture(surface.texture);
14054 rsurface.lightmaptexture = NULL;
14055 rsurface.deluxemaptexture = NULL;
14056 rsurface.uselightmaptexture = false;
14057 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);