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 if (r_shadow_bouncegridtexture)
5009 permutation |= SHADERPERMUTATION_BOUNCEGRID;
5010 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5011 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5013 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5015 if (r_glsl_offsetmapping.integer)
5017 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5018 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5019 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5020 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5021 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5023 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5024 if (r_glsl_offsetmapping_reliefmapping.integer)
5025 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5028 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5029 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5030 // directional model lighting
5031 mode = SHADERMODE_LIGHTDIRECTION;
5032 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5033 permutation |= SHADERPERMUTATION_GLOW;
5034 permutation |= SHADERPERMUTATION_DIFFUSE;
5035 if (specularscale > 0)
5036 permutation |= SHADERPERMUTATION_SPECULAR;
5037 if (r_refdef.fogenabled)
5038 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5039 if (rsurface.texture->colormapping)
5040 permutation |= SHADERPERMUTATION_COLORMAPPING;
5041 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5043 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5044 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5046 if (r_shadow_shadowmapsampler)
5047 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5048 if (r_shadow_shadowmappcf > 1)
5049 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5050 else if (r_shadow_shadowmappcf)
5051 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5053 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5054 permutation |= SHADERPERMUTATION_REFLECTION;
5055 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5056 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5057 if (rsurface.texture->reflectmasktexture)
5058 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5059 if (r_shadow_bouncegridtexture)
5060 permutation |= SHADERPERMUTATION_BOUNCEGRID;
5061 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5062 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5064 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5066 if (r_glsl_offsetmapping.integer)
5068 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5069 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5070 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5071 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5072 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5074 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5075 if (r_glsl_offsetmapping_reliefmapping.integer)
5076 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5079 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5080 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5081 // ambient model lighting
5082 mode = SHADERMODE_LIGHTDIRECTION;
5083 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5084 permutation |= SHADERPERMUTATION_GLOW;
5085 if (r_refdef.fogenabled)
5086 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5087 if (rsurface.texture->colormapping)
5088 permutation |= SHADERPERMUTATION_COLORMAPPING;
5089 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5091 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5092 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5094 if (r_shadow_shadowmapsampler)
5095 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5096 if (r_shadow_shadowmappcf > 1)
5097 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5098 else if (r_shadow_shadowmappcf)
5099 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5101 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5102 permutation |= SHADERPERMUTATION_REFLECTION;
5103 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5104 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5105 if (rsurface.texture->reflectmasktexture)
5106 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5107 if (r_shadow_bouncegridtexture)
5108 permutation |= SHADERPERMUTATION_BOUNCEGRID;
5109 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5110 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5114 if (r_glsl_offsetmapping.integer)
5116 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5117 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5118 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5119 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5120 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5122 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5123 if (r_glsl_offsetmapping_reliefmapping.integer)
5124 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5127 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5128 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5130 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5131 permutation |= SHADERPERMUTATION_GLOW;
5132 if (r_refdef.fogenabled)
5133 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5134 if (rsurface.texture->colormapping)
5135 permutation |= SHADERPERMUTATION_COLORMAPPING;
5136 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5138 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5139 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5141 if (r_shadow_shadowmapsampler)
5142 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5143 if (r_shadow_shadowmappcf > 1)
5144 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5145 else if (r_shadow_shadowmappcf)
5146 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5148 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5149 permutation |= SHADERPERMUTATION_REFLECTION;
5150 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5151 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5152 if (rsurface.texture->reflectmasktexture)
5153 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5154 if (FAKELIGHT_ENABLED)
5156 // fake lightmapping (q1bsp, q3bsp, fullbright map)
5157 mode = SHADERMODE_FAKELIGHT;
5158 permutation |= SHADERPERMUTATION_DIFFUSE;
5159 if (specularscale > 0)
5160 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5162 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5164 // deluxemapping (light direction texture)
5165 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5166 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5168 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5169 permutation |= SHADERPERMUTATION_DIFFUSE;
5170 if (specularscale > 0)
5171 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5173 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5175 // fake deluxemapping (uniform light direction in tangentspace)
5176 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5177 permutation |= SHADERPERMUTATION_DIFFUSE;
5178 if (specularscale > 0)
5179 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5181 else if (rsurface.uselightmaptexture)
5183 // ordinary lightmapping (q1bsp, q3bsp)
5184 mode = SHADERMODE_LIGHTMAP;
5188 // ordinary vertex coloring (q3bsp)
5189 mode = SHADERMODE_VERTEXCOLOR;
5191 if (r_shadow_bouncegridtexture)
5192 permutation |= SHADERPERMUTATION_BOUNCEGRID;
5193 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5194 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5197 colormod = dummy_colormod;
5198 switch(vid.renderpath)
5200 case RENDERPATH_D3D9:
5202 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);
5203 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5204 R_SetupShader_SetPermutationHLSL(mode, permutation);
5205 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5206 if (mode == SHADERMODE_LIGHTSOURCE)
5208 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5209 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5213 if (mode == SHADERMODE_LIGHTDIRECTION)
5215 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5218 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5219 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5220 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5221 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5222 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5224 if (mode == SHADERMODE_LIGHTSOURCE)
5226 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5227 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5228 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5229 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5230 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5232 // additive passes are only darkened by fog, not tinted
5233 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5234 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5238 if (mode == SHADERMODE_FLATCOLOR)
5240 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5242 else if (mode == SHADERMODE_LIGHTDIRECTION)
5244 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]);
5245 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5246 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);
5247 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);
5248 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5249 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5250 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5254 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5255 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5256 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);
5257 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);
5258 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5260 // additive passes are only darkened by fog, not tinted
5261 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5262 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5264 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5265 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);
5266 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5267 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5268 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5269 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5270 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5271 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5272 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5273 if (mode == SHADERMODE_WATER)
5274 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5276 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5277 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5278 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5279 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));
5280 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5281 if (rsurface.texture->pantstexture)
5282 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5284 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5285 if (rsurface.texture->shirttexture)
5286 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5288 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5289 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5290 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5291 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5292 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5293 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5294 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5295 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5297 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5298 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5299 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5300 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5301 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5302 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5303 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5304 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5305 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5306 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5307 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5308 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5309 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5310 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5311 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5312 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5313 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5314 if (rsurfacepass == RSURFPASS_BACKGROUND)
5316 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5317 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5318 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5322 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5324 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5325 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5326 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5327 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5328 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5330 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5331 if (rsurface.rtlight)
5333 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5334 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5339 case RENDERPATH_D3D10:
5340 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5342 case RENDERPATH_D3D11:
5343 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5345 case RENDERPATH_GL20:
5346 case RENDERPATH_GLES2:
5347 if (!vid.useinterleavedarrays)
5349 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);
5350 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5351 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5352 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5353 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5354 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5355 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5356 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5360 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);
5361 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5363 R_SetupShader_SetPermutationGLSL(mode, permutation);
5364 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5365 if (mode == SHADERMODE_LIGHTSOURCE)
5367 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5368 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5369 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5370 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5371 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5372 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);
5374 // additive passes are only darkened by fog, not tinted
5375 if (r_glsl_permutation->loc_FogColor >= 0)
5376 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5377 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5381 if (mode == SHADERMODE_FLATCOLOR)
5383 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5385 else if (mode == SHADERMODE_LIGHTDIRECTION)
5387 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]);
5388 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]);
5389 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);
5390 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);
5391 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);
5392 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]);
5393 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]);
5397 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]);
5398 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]);
5399 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);
5400 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);
5401 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);
5403 // additive passes are only darkened by fog, not tinted
5404 if (r_glsl_permutation->loc_FogColor >= 0)
5406 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5407 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5409 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5411 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);
5412 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]);
5413 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]);
5414 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]);
5415 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]);
5416 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5417 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5418 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5419 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]);
5421 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5422 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5423 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5424 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]);
5425 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]);
5427 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5428 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));
5429 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5430 if (r_glsl_permutation->loc_Color_Pants >= 0)
5432 if (rsurface.texture->pantstexture)
5433 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5435 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5437 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5439 if (rsurface.texture->shirttexture)
5440 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5442 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5444 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]);
5445 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5446 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5447 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5448 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5449 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]);
5450 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5451 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);}
5452 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity);
5454 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
5455 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
5456 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
5457 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
5458 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
5459 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
5460 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
5461 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
5462 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
5463 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
5464 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
5465 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
5466 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
5467 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
5468 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);
5469 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
5470 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
5471 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5472 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5473 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
5474 if (rsurfacepass == RSURFPASS_BACKGROUND)
5476 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);
5477 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);
5478 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);
5482 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);
5484 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
5485 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
5486 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
5487 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
5488 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5490 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
5491 if (rsurface.rtlight)
5493 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
5494 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
5497 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
5500 case RENDERPATH_GL13:
5501 case RENDERPATH_GL11:
5503 case RENDERPATH_SOFT:
5504 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);
5505 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
5506 R_SetupShader_SetPermutationSoft(mode, permutation);
5507 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
5508 if (mode == SHADERMODE_LIGHTSOURCE)
5510 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
5511 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5512 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5513 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5514 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5515 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5517 // additive passes are only darkened by fog, not tinted
5518 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
5519 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5523 if (mode == SHADERMODE_FLATCOLOR)
5525 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5527 else if (mode == SHADERMODE_LIGHTDIRECTION)
5529 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]);
5530 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5531 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);
5532 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);
5533 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5534 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]);
5535 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5539 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5540 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5541 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);
5542 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);
5543 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5545 // additive passes are only darkened by fog, not tinted
5546 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5547 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
5549 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5550 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);
5551 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5552 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5553 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]);
5554 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]);
5555 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5556 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
5557 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5558 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5560 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
5561 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
5562 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
5563 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5564 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]);
5566 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5567 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));
5568 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5569 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
5571 if (rsurface.texture->pantstexture)
5572 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5574 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
5576 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
5578 if (rsurface.texture->shirttexture)
5579 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5581 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
5583 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5584 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
5585 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
5586 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
5587 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5588 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5589 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5591 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5592 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5593 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5594 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5595 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5596 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5597 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5598 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5599 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5600 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5601 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5602 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5603 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5604 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5605 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5606 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5607 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5608 if (rsurfacepass == RSURFPASS_BACKGROUND)
5610 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5611 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5612 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5616 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5618 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5619 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5620 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5621 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5622 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5624 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5625 if (rsurface.rtlight)
5627 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5628 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5635 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5637 // select a permutation of the lighting shader appropriate to this
5638 // combination of texture, entity, light source, and fogging, only use the
5639 // minimum features necessary to avoid wasting rendering time in the
5640 // fragment shader on features that are not being used
5641 unsigned int permutation = 0;
5642 unsigned int mode = 0;
5643 const float *lightcolorbase = rtlight->currentcolor;
5644 float ambientscale = rtlight->ambientscale;
5645 float diffusescale = rtlight->diffusescale;
5646 float specularscale = rtlight->specularscale;
5647 // this is the location of the light in view space
5648 vec3_t viewlightorigin;
5649 // this transforms from view space (camera) to light space (cubemap)
5650 matrix4x4_t viewtolight;
5651 matrix4x4_t lighttoview;
5652 float viewtolight16f[16];
5653 float range = 1.0f / r_shadow_deferred_8bitrange.value;
5655 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
5656 if (rtlight->currentcubemap != r_texture_whitecube)
5657 permutation |= SHADERPERMUTATION_CUBEFILTER;
5658 if (diffusescale > 0)
5659 permutation |= SHADERPERMUTATION_DIFFUSE;
5660 if (specularscale > 0)
5661 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5662 if (r_shadow_usingshadowmap2d)
5664 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5665 if (r_shadow_shadowmapvsdct)
5666 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5668 if (r_shadow_shadowmapsampler)
5669 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5670 if (r_shadow_shadowmappcf > 1)
5671 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5672 else if (r_shadow_shadowmappcf)
5673 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5675 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
5676 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
5677 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
5678 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
5679 switch(vid.renderpath)
5681 case RENDERPATH_D3D9:
5683 R_SetupShader_SetPermutationHLSL(mode, permutation);
5684 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5685 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
5686 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
5687 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
5688 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
5689 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5690 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5691 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5692 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5693 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5695 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5696 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
5697 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5698 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5699 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
5700 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5703 case RENDERPATH_D3D10:
5704 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5706 case RENDERPATH_D3D11:
5707 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5709 case RENDERPATH_GL20:
5710 case RENDERPATH_GLES2:
5711 R_SetupShader_SetPermutationGLSL(mode, permutation);
5712 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5713 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
5714 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);
5715 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);
5716 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);
5717 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]);
5718 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]);
5719 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));
5720 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]);
5721 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
5723 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
5724 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
5725 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
5726 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
5727 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
5728 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
5730 case RENDERPATH_GL13:
5731 case RENDERPATH_GL11:
5733 case RENDERPATH_SOFT:
5734 R_SetupShader_SetPermutationGLSL(mode, permutation);
5735 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5736 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
5737 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
5738 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
5739 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
5740 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5741 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]);
5742 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));
5743 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5744 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5746 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5747 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5748 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5749 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5750 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
5751 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5756 #define SKINFRAME_HASH 1024
5760 int loadsequence; // incremented each level change
5761 memexpandablearray_t array;
5762 skinframe_t *hash[SKINFRAME_HASH];
5765 r_skinframe_t r_skinframe;
5767 void R_SkinFrame_PrepareForPurge(void)
5769 r_skinframe.loadsequence++;
5770 // wrap it without hitting zero
5771 if (r_skinframe.loadsequence >= 200)
5772 r_skinframe.loadsequence = 1;
5775 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5779 // mark the skinframe as used for the purging code
5780 skinframe->loadsequence = r_skinframe.loadsequence;
5783 void R_SkinFrame_Purge(void)
5787 for (i = 0;i < SKINFRAME_HASH;i++)
5789 for (s = r_skinframe.hash[i];s;s = s->next)
5791 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5793 if (s->merged == s->base)
5795 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5796 R_PurgeTexture(s->stain );s->stain = NULL;
5797 R_PurgeTexture(s->merged);s->merged = NULL;
5798 R_PurgeTexture(s->base );s->base = NULL;
5799 R_PurgeTexture(s->pants );s->pants = NULL;
5800 R_PurgeTexture(s->shirt );s->shirt = NULL;
5801 R_PurgeTexture(s->nmap );s->nmap = NULL;
5802 R_PurgeTexture(s->gloss );s->gloss = NULL;
5803 R_PurgeTexture(s->glow );s->glow = NULL;
5804 R_PurgeTexture(s->fog );s->fog = NULL;
5805 R_PurgeTexture(s->reflect);s->reflect = NULL;
5806 s->loadsequence = 0;
5812 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5814 char basename[MAX_QPATH];
5816 Image_StripImageExtension(name, basename, sizeof(basename));
5818 if( last == NULL ) {
5820 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5821 item = r_skinframe.hash[hashindex];
5826 // linearly search through the hash bucket
5827 for( ; item ; item = item->next ) {
5828 if( !strcmp( item->basename, basename ) ) {
5835 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5839 char basename[MAX_QPATH];
5841 Image_StripImageExtension(name, basename, sizeof(basename));
5843 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5844 for (item = r_skinframe.hash[hashindex];item;item = item->next)
5845 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5849 rtexture_t *dyntexture;
5850 // check whether its a dynamic texture
5851 dyntexture = CL_GetDynTexture( basename );
5852 if (!add && !dyntexture)
5854 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5855 memset(item, 0, sizeof(*item));
5856 strlcpy(item->basename, basename, sizeof(item->basename));
5857 item->base = dyntexture; // either NULL or dyntexture handle
5858 item->textureflags = textureflags;
5859 item->comparewidth = comparewidth;
5860 item->compareheight = compareheight;
5861 item->comparecrc = comparecrc;
5862 item->next = r_skinframe.hash[hashindex];
5863 r_skinframe.hash[hashindex] = item;
5865 else if( item->base == NULL )
5867 rtexture_t *dyntexture;
5868 // check whether its a dynamic texture
5869 // 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]
5870 dyntexture = CL_GetDynTexture( basename );
5871 item->base = dyntexture; // either NULL or dyntexture handle
5874 R_SkinFrame_MarkUsed(item);
5878 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5880 unsigned long long avgcolor[5], wsum; \
5888 for(pix = 0; pix < cnt; ++pix) \
5891 for(comp = 0; comp < 3; ++comp) \
5893 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5896 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5898 for(comp = 0; comp < 3; ++comp) \
5899 avgcolor[comp] += getpixel * w; \
5902 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5903 avgcolor[4] += getpixel; \
5905 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5907 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5908 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5909 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5910 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5913 extern cvar_t gl_picmip;
5914 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5917 unsigned char *pixels;
5918 unsigned char *bumppixels;
5919 unsigned char *basepixels = NULL;
5920 int basepixels_width = 0;
5921 int basepixels_height = 0;
5922 skinframe_t *skinframe;
5923 rtexture_t *ddsbase = NULL;
5924 qboolean ddshasalpha = false;
5925 float ddsavgcolor[4];
5926 char basename[MAX_QPATH];
5927 int miplevel = R_PicmipForFlags(textureflags);
5928 int savemiplevel = miplevel;
5931 if (cls.state == ca_dedicated)
5934 // return an existing skinframe if already loaded
5935 // if loading of the first image fails, don't make a new skinframe as it
5936 // would cause all future lookups of this to be missing
5937 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5938 if (skinframe && skinframe->base)
5941 Image_StripImageExtension(name, basename, sizeof(basename));
5943 // check for DDS texture file first
5944 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
5946 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
5947 if (basepixels == NULL)
5951 // FIXME handle miplevel
5953 if (developer_loading.integer)
5954 Con_Printf("loading skin \"%s\"\n", name);
5956 // we've got some pixels to store, so really allocate this new texture now
5958 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5959 skinframe->stain = NULL;
5960 skinframe->merged = NULL;
5961 skinframe->base = NULL;
5962 skinframe->pants = NULL;
5963 skinframe->shirt = NULL;
5964 skinframe->nmap = NULL;
5965 skinframe->gloss = NULL;
5966 skinframe->glow = NULL;
5967 skinframe->fog = NULL;
5968 skinframe->reflect = NULL;
5969 skinframe->hasalpha = false;
5973 skinframe->base = ddsbase;
5974 skinframe->hasalpha = ddshasalpha;
5975 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5976 if (r_loadfog && skinframe->hasalpha)
5977 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
5978 //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]);
5982 basepixels_width = image_width;
5983 basepixels_height = image_height;
5984 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);
5985 if (textureflags & TEXF_ALPHA)
5987 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5989 if (basepixels[j] < 255)
5991 skinframe->hasalpha = true;
5995 if (r_loadfog && skinframe->hasalpha)
5997 // has transparent pixels
5998 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5999 for (j = 0;j < image_width * image_height * 4;j += 4)
6004 pixels[j+3] = basepixels[j+3];
6006 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);
6010 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6011 //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]);
6012 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6013 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6014 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6015 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6020 mymiplevel = savemiplevel;
6021 if (r_loadnormalmap)
6022 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);
6023 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6025 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6026 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6027 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6028 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6031 // _norm is the name used by tenebrae and has been adopted as standard
6032 if (r_loadnormalmap && skinframe->nmap == NULL)
6034 mymiplevel = savemiplevel;
6035 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6037 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);
6041 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6043 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6044 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6045 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);
6047 Mem_Free(bumppixels);
6049 else if (r_shadow_bumpscale_basetexture.value > 0)
6051 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6052 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6053 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);
6056 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6057 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6060 // _luma is supported only for tenebrae compatibility
6061 // _glow is the preferred name
6062 mymiplevel = savemiplevel;
6063 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))))
6065 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);
6066 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6067 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6068 Mem_Free(pixels);pixels = NULL;
6071 mymiplevel = savemiplevel;
6072 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6074 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);
6075 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6076 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6081 mymiplevel = savemiplevel;
6082 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6084 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);
6085 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6086 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6091 mymiplevel = savemiplevel;
6092 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6094 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);
6095 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6096 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6101 mymiplevel = savemiplevel;
6102 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6104 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);
6105 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6106 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6112 Mem_Free(basepixels);
6117 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6118 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6121 unsigned char *temp1, *temp2;
6122 skinframe_t *skinframe;
6124 if (cls.state == ca_dedicated)
6127 // if already loaded just return it, otherwise make a new skinframe
6128 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6129 if (skinframe && skinframe->base)
6132 skinframe->stain = NULL;
6133 skinframe->merged = NULL;
6134 skinframe->base = NULL;
6135 skinframe->pants = NULL;
6136 skinframe->shirt = NULL;
6137 skinframe->nmap = NULL;
6138 skinframe->gloss = NULL;
6139 skinframe->glow = NULL;
6140 skinframe->fog = NULL;
6141 skinframe->reflect = NULL;
6142 skinframe->hasalpha = false;
6144 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6148 if (developer_loading.integer)
6149 Con_Printf("loading 32bit skin \"%s\"\n", name);
6151 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6153 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6154 temp2 = temp1 + width * height * 4;
6155 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6156 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);
6159 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6160 if (textureflags & TEXF_ALPHA)
6162 for (i = 3;i < width * height * 4;i += 4)
6164 if (skindata[i] < 255)
6166 skinframe->hasalpha = true;
6170 if (r_loadfog && skinframe->hasalpha)
6172 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6173 memcpy(fogpixels, skindata, width * height * 4);
6174 for (i = 0;i < width * height * 4;i += 4)
6175 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6176 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6177 Mem_Free(fogpixels);
6181 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6182 //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]);
6187 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6191 skinframe_t *skinframe;
6193 if (cls.state == ca_dedicated)
6196 // if already loaded just return it, otherwise make a new skinframe
6197 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6198 if (skinframe && skinframe->base)
6201 skinframe->stain = NULL;
6202 skinframe->merged = NULL;
6203 skinframe->base = NULL;
6204 skinframe->pants = NULL;
6205 skinframe->shirt = NULL;
6206 skinframe->nmap = NULL;
6207 skinframe->gloss = NULL;
6208 skinframe->glow = NULL;
6209 skinframe->fog = NULL;
6210 skinframe->reflect = NULL;
6211 skinframe->hasalpha = false;
6213 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6217 if (developer_loading.integer)
6218 Con_Printf("loading quake skin \"%s\"\n", name);
6220 // 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)
6221 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
6222 memcpy(skinframe->qpixels, skindata, width*height);
6223 skinframe->qwidth = width;
6224 skinframe->qheight = height;
6227 for (i = 0;i < width * height;i++)
6228 featuresmask |= palette_featureflags[skindata[i]];
6230 skinframe->hasalpha = false;
6231 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6232 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6233 skinframe->qgeneratemerged = true;
6234 skinframe->qgeneratebase = skinframe->qhascolormapping;
6235 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6237 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6238 //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]);
6243 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6247 unsigned char *skindata;
6249 if (!skinframe->qpixels)
6252 if (!skinframe->qhascolormapping)
6253 colormapped = false;
6257 if (!skinframe->qgeneratebase)
6262 if (!skinframe->qgeneratemerged)
6266 width = skinframe->qwidth;
6267 height = skinframe->qheight;
6268 skindata = skinframe->qpixels;
6270 if (skinframe->qgeneratenmap)
6272 unsigned char *temp1, *temp2;
6273 skinframe->qgeneratenmap = false;
6274 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6275 temp2 = temp1 + width * height * 4;
6276 // use either a custom palette or the quake palette
6277 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6278 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6279 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);
6283 if (skinframe->qgenerateglow)
6285 skinframe->qgenerateglow = false;
6286 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6291 skinframe->qgeneratebase = false;
6292 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);
6293 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6294 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6298 skinframe->qgeneratemerged = false;
6299 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);
6302 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6304 Mem_Free(skinframe->qpixels);
6305 skinframe->qpixels = NULL;
6309 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)
6312 skinframe_t *skinframe;
6314 if (cls.state == ca_dedicated)
6317 // if already loaded just return it, otherwise make a new skinframe
6318 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6319 if (skinframe && skinframe->base)
6322 skinframe->stain = NULL;
6323 skinframe->merged = NULL;
6324 skinframe->base = NULL;
6325 skinframe->pants = NULL;
6326 skinframe->shirt = NULL;
6327 skinframe->nmap = NULL;
6328 skinframe->gloss = NULL;
6329 skinframe->glow = NULL;
6330 skinframe->fog = NULL;
6331 skinframe->reflect = NULL;
6332 skinframe->hasalpha = false;
6334 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6338 if (developer_loading.integer)
6339 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6341 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6342 if (textureflags & TEXF_ALPHA)
6344 for (i = 0;i < width * height;i++)
6346 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6348 skinframe->hasalpha = true;
6352 if (r_loadfog && skinframe->hasalpha)
6353 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6356 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6357 //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]);
6362 skinframe_t *R_SkinFrame_LoadMissing(void)
6364 skinframe_t *skinframe;
6366 if (cls.state == ca_dedicated)
6369 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6370 skinframe->stain = NULL;
6371 skinframe->merged = NULL;
6372 skinframe->base = NULL;
6373 skinframe->pants = NULL;
6374 skinframe->shirt = NULL;
6375 skinframe->nmap = NULL;
6376 skinframe->gloss = NULL;
6377 skinframe->glow = NULL;
6378 skinframe->fog = NULL;
6379 skinframe->reflect = NULL;
6380 skinframe->hasalpha = false;
6382 skinframe->avgcolor[0] = rand() / RAND_MAX;
6383 skinframe->avgcolor[1] = rand() / RAND_MAX;
6384 skinframe->avgcolor[2] = rand() / RAND_MAX;
6385 skinframe->avgcolor[3] = 1;
6390 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6391 typedef struct suffixinfo_s
6394 qboolean flipx, flipy, flipdiagonal;
6397 static suffixinfo_t suffix[3][6] =
6400 {"px", false, false, false},
6401 {"nx", false, false, false},
6402 {"py", false, false, false},
6403 {"ny", false, false, false},
6404 {"pz", false, false, false},
6405 {"nz", false, false, false}
6408 {"posx", false, false, false},
6409 {"negx", false, false, false},
6410 {"posy", false, false, false},
6411 {"negy", false, false, false},
6412 {"posz", false, false, false},
6413 {"negz", false, false, false}
6416 {"rt", true, false, true},
6417 {"lf", false, true, true},
6418 {"ft", true, true, false},
6419 {"bk", false, false, false},
6420 {"up", true, false, true},
6421 {"dn", true, false, true}
6425 static int componentorder[4] = {0, 1, 2, 3};
6427 rtexture_t *R_LoadCubemap(const char *basename)
6429 int i, j, cubemapsize;
6430 unsigned char *cubemappixels, *image_buffer;
6431 rtexture_t *cubemaptexture;
6433 // must start 0 so the first loadimagepixels has no requested width/height
6435 cubemappixels = NULL;
6436 cubemaptexture = NULL;
6437 // keep trying different suffix groups (posx, px, rt) until one loads
6438 for (j = 0;j < 3 && !cubemappixels;j++)
6440 // load the 6 images in the suffix group
6441 for (i = 0;i < 6;i++)
6443 // generate an image name based on the base and and suffix
6444 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6446 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
6448 // an image loaded, make sure width and height are equal
6449 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6451 // if this is the first image to load successfully, allocate the cubemap memory
6452 if (!cubemappixels && image_width >= 1)
6454 cubemapsize = image_width;
6455 // note this clears to black, so unavailable sides are black
6456 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6458 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6460 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);
6463 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6465 Mem_Free(image_buffer);
6469 // if a cubemap loaded, upload it
6472 if (developer_loading.integer)
6473 Con_Printf("loading cubemap \"%s\"\n", basename);
6475 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6476 Mem_Free(cubemappixels);
6480 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6481 if (developer_loading.integer)
6483 Con_Printf("(tried tried images ");
6484 for (j = 0;j < 3;j++)
6485 for (i = 0;i < 6;i++)
6486 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6487 Con_Print(" and was unable to find any of them).\n");
6490 return cubemaptexture;
6493 rtexture_t *R_GetCubemap(const char *basename)
6496 for (i = 0;i < r_texture_numcubemaps;i++)
6497 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6498 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6499 if (i >= MAX_CUBEMAPS)
6500 return r_texture_whitecube;
6501 r_texture_numcubemaps++;
6502 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6503 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6504 return r_texture_cubemaps[i].texture;
6507 void R_FreeCubemaps(void)
6510 for (i = 0;i < r_texture_numcubemaps;i++)
6512 if (developer_loading.integer)
6513 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6514 if (r_texture_cubemaps[i].texture)
6515 R_FreeTexture(r_texture_cubemaps[i].texture);
6517 r_texture_numcubemaps = 0;
6520 void R_Main_FreeViewCache(void)
6522 if (r_refdef.viewcache.entityvisible)
6523 Mem_Free(r_refdef.viewcache.entityvisible);
6524 if (r_refdef.viewcache.world_pvsbits)
6525 Mem_Free(r_refdef.viewcache.world_pvsbits);
6526 if (r_refdef.viewcache.world_leafvisible)
6527 Mem_Free(r_refdef.viewcache.world_leafvisible);
6528 if (r_refdef.viewcache.world_surfacevisible)
6529 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6530 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6533 void R_Main_ResizeViewCache(void)
6535 int numentities = r_refdef.scene.numentities;
6536 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6537 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6538 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6539 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6540 if (r_refdef.viewcache.maxentities < numentities)
6542 r_refdef.viewcache.maxentities = numentities;
6543 if (r_refdef.viewcache.entityvisible)
6544 Mem_Free(r_refdef.viewcache.entityvisible);
6545 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6547 if (r_refdef.viewcache.world_numclusters != numclusters)
6549 r_refdef.viewcache.world_numclusters = numclusters;
6550 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6551 if (r_refdef.viewcache.world_pvsbits)
6552 Mem_Free(r_refdef.viewcache.world_pvsbits);
6553 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6555 if (r_refdef.viewcache.world_numleafs != numleafs)
6557 r_refdef.viewcache.world_numleafs = numleafs;
6558 if (r_refdef.viewcache.world_leafvisible)
6559 Mem_Free(r_refdef.viewcache.world_leafvisible);
6560 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6562 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6564 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6565 if (r_refdef.viewcache.world_surfacevisible)
6566 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6567 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6571 extern rtexture_t *loadingscreentexture;
6572 void gl_main_start(void)
6574 loadingscreentexture = NULL;
6575 r_texture_blanknormalmap = NULL;
6576 r_texture_white = NULL;
6577 r_texture_grey128 = NULL;
6578 r_texture_black = NULL;
6579 r_texture_whitecube = NULL;
6580 r_texture_normalizationcube = NULL;
6581 r_texture_fogattenuation = NULL;
6582 r_texture_fogheighttexture = NULL;
6583 r_texture_gammaramps = NULL;
6584 r_texture_numcubemaps = 0;
6586 r_loaddds = r_texture_dds_load.integer != 0;
6587 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6589 switch(vid.renderpath)
6591 case RENDERPATH_GL20:
6592 case RENDERPATH_D3D9:
6593 case RENDERPATH_D3D10:
6594 case RENDERPATH_D3D11:
6595 case RENDERPATH_SOFT:
6596 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6597 Cvar_SetValueQuick(&gl_combine, 1);
6598 Cvar_SetValueQuick(&r_glsl, 1);
6599 r_loadnormalmap = true;
6603 case RENDERPATH_GL13:
6604 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6605 Cvar_SetValueQuick(&gl_combine, 1);
6606 Cvar_SetValueQuick(&r_glsl, 0);
6607 r_loadnormalmap = false;
6608 r_loadgloss = false;
6611 case RENDERPATH_GL11:
6612 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6613 Cvar_SetValueQuick(&gl_combine, 0);
6614 Cvar_SetValueQuick(&r_glsl, 0);
6615 r_loadnormalmap = false;
6616 r_loadgloss = false;
6619 case RENDERPATH_GLES2:
6620 Cvar_SetValueQuick(&r_textureunits, 1);
6621 Cvar_SetValueQuick(&gl_combine, 1);
6622 Cvar_SetValueQuick(&r_glsl, 1);
6623 r_loadnormalmap = true;
6624 r_loadgloss = false;
6630 R_FrameData_Reset();
6634 memset(r_queries, 0, sizeof(r_queries));
6636 r_qwskincache = NULL;
6637 r_qwskincache_size = 0;
6639 // set up r_skinframe loading system for textures
6640 memset(&r_skinframe, 0, sizeof(r_skinframe));
6641 r_skinframe.loadsequence = 1;
6642 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6644 r_main_texturepool = R_AllocTexturePool();
6645 R_BuildBlankTextures();
6647 if (vid.support.arb_texture_cube_map)
6650 R_BuildNormalizationCube();
6652 r_texture_fogattenuation = NULL;
6653 r_texture_fogheighttexture = NULL;
6654 r_texture_gammaramps = NULL;
6655 //r_texture_fogintensity = NULL;
6656 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6657 memset(&r_waterstate, 0, sizeof(r_waterstate));
6658 r_glsl_permutation = NULL;
6659 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6660 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
6661 glslshaderstring = NULL;
6663 r_hlsl_permutation = NULL;
6664 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
6665 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
6667 hlslshaderstring = NULL;
6668 memset(&r_svbsp, 0, sizeof (r_svbsp));
6670 r_refdef.fogmasktable_density = 0;
6673 void gl_main_shutdown(void)
6676 R_FrameData_Reset();
6678 R_Main_FreeViewCache();
6680 switch(vid.renderpath)
6682 case RENDERPATH_GL11:
6683 case RENDERPATH_GL13:
6684 case RENDERPATH_GL20:
6685 case RENDERPATH_GLES2:
6687 qglDeleteQueriesARB(r_maxqueries, r_queries);
6689 case RENDERPATH_D3D9:
6690 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6692 case RENDERPATH_D3D10:
6693 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6695 case RENDERPATH_D3D11:
6696 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6698 case RENDERPATH_SOFT:
6704 memset(r_queries, 0, sizeof(r_queries));
6706 r_qwskincache = NULL;
6707 r_qwskincache_size = 0;
6709 // clear out the r_skinframe state
6710 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
6711 memset(&r_skinframe, 0, sizeof(r_skinframe));
6714 Mem_Free(r_svbsp.nodes);
6715 memset(&r_svbsp, 0, sizeof (r_svbsp));
6716 R_FreeTexturePool(&r_main_texturepool);
6717 loadingscreentexture = NULL;
6718 r_texture_blanknormalmap = NULL;
6719 r_texture_white = NULL;
6720 r_texture_grey128 = NULL;
6721 r_texture_black = NULL;
6722 r_texture_whitecube = NULL;
6723 r_texture_normalizationcube = NULL;
6724 r_texture_fogattenuation = NULL;
6725 r_texture_fogheighttexture = NULL;
6726 r_texture_gammaramps = NULL;
6727 r_texture_numcubemaps = 0;
6728 //r_texture_fogintensity = NULL;
6729 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6730 memset(&r_waterstate, 0, sizeof(r_waterstate));
6733 r_glsl_permutation = NULL;
6734 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6735 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
6736 glslshaderstring = NULL;
6738 r_hlsl_permutation = NULL;
6739 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
6740 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
6742 hlslshaderstring = NULL;
6745 extern void CL_ParseEntityLump(char *entitystring);
6746 void gl_main_newmap(void)
6748 // FIXME: move this code to client
6749 char *entities, entname[MAX_QPATH];
6751 Mem_Free(r_qwskincache);
6752 r_qwskincache = NULL;
6753 r_qwskincache_size = 0;
6756 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
6757 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
6759 CL_ParseEntityLump(entities);
6763 if (cl.worldmodel->brush.entities)
6764 CL_ParseEntityLump(cl.worldmodel->brush.entities);
6766 R_Main_FreeViewCache();
6768 R_FrameData_Reset();
6771 void GL_Main_Init(void)
6773 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
6775 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
6776 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
6777 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
6778 if (gamemode == GAME_NEHAHRA)
6780 Cvar_RegisterVariable (&gl_fogenable);
6781 Cvar_RegisterVariable (&gl_fogdensity);
6782 Cvar_RegisterVariable (&gl_fogred);
6783 Cvar_RegisterVariable (&gl_foggreen);
6784 Cvar_RegisterVariable (&gl_fogblue);
6785 Cvar_RegisterVariable (&gl_fogstart);
6786 Cvar_RegisterVariable (&gl_fogend);
6787 Cvar_RegisterVariable (&gl_skyclip);
6789 Cvar_RegisterVariable(&r_motionblur);
6790 Cvar_RegisterVariable(&r_motionblur_maxblur);
6791 Cvar_RegisterVariable(&r_motionblur_bmin);
6792 Cvar_RegisterVariable(&r_motionblur_vmin);
6793 Cvar_RegisterVariable(&r_motionblur_vmax);
6794 Cvar_RegisterVariable(&r_motionblur_vcoeff);
6795 Cvar_RegisterVariable(&r_motionblur_randomize);
6796 Cvar_RegisterVariable(&r_damageblur);
6797 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
6798 Cvar_RegisterVariable(&r_equalize_entities_minambient);
6799 Cvar_RegisterVariable(&r_equalize_entities_by);
6800 Cvar_RegisterVariable(&r_equalize_entities_to);
6801 Cvar_RegisterVariable(&r_depthfirst);
6802 Cvar_RegisterVariable(&r_useinfinitefarclip);
6803 Cvar_RegisterVariable(&r_farclip_base);
6804 Cvar_RegisterVariable(&r_farclip_world);
6805 Cvar_RegisterVariable(&r_nearclip);
6806 Cvar_RegisterVariable(&r_showbboxes);
6807 Cvar_RegisterVariable(&r_showsurfaces);
6808 Cvar_RegisterVariable(&r_showtris);
6809 Cvar_RegisterVariable(&r_shownormals);
6810 Cvar_RegisterVariable(&r_showlighting);
6811 Cvar_RegisterVariable(&r_showshadowvolumes);
6812 Cvar_RegisterVariable(&r_showcollisionbrushes);
6813 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
6814 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
6815 Cvar_RegisterVariable(&r_showdisabledepthtest);
6816 Cvar_RegisterVariable(&r_drawportals);
6817 Cvar_RegisterVariable(&r_drawentities);
6818 Cvar_RegisterVariable(&r_draw2d);
6819 Cvar_RegisterVariable(&r_drawworld);
6820 Cvar_RegisterVariable(&r_cullentities_trace);
6821 Cvar_RegisterVariable(&r_cullentities_trace_samples);
6822 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
6823 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
6824 Cvar_RegisterVariable(&r_cullentities_trace_delay);
6825 Cvar_RegisterVariable(&r_drawviewmodel);
6826 Cvar_RegisterVariable(&r_drawexteriormodel);
6827 Cvar_RegisterVariable(&r_speeds);
6828 Cvar_RegisterVariable(&r_fullbrights);
6829 Cvar_RegisterVariable(&r_wateralpha);
6830 Cvar_RegisterVariable(&r_dynamic);
6831 Cvar_RegisterVariable(&r_fakelight);
6832 Cvar_RegisterVariable(&r_fakelight_intensity);
6833 Cvar_RegisterVariable(&r_fullbright);
6834 Cvar_RegisterVariable(&r_shadows);
6835 Cvar_RegisterVariable(&r_shadows_darken);
6836 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
6837 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
6838 Cvar_RegisterVariable(&r_shadows_throwdistance);
6839 Cvar_RegisterVariable(&r_shadows_throwdirection);
6840 Cvar_RegisterVariable(&r_shadows_focus);
6841 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
6842 Cvar_RegisterVariable(&r_q1bsp_skymasking);
6843 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
6844 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
6845 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
6846 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
6847 Cvar_RegisterVariable(&r_fog_exp2);
6848 Cvar_RegisterVariable(&r_drawfog);
6849 Cvar_RegisterVariable(&r_transparentdepthmasking);
6850 Cvar_RegisterVariable(&r_texture_dds_load);
6851 Cvar_RegisterVariable(&r_texture_dds_save);
6852 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
6853 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
6854 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
6855 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
6856 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
6857 Cvar_RegisterVariable(&r_textureunits);
6858 Cvar_RegisterVariable(&gl_combine);
6859 Cvar_RegisterVariable(&r_glsl);
6860 Cvar_RegisterVariable(&r_glsl_deluxemapping);
6861 Cvar_RegisterVariable(&r_glsl_offsetmapping);
6862 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
6863 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
6864 Cvar_RegisterVariable(&r_glsl_postprocess);
6865 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
6866 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
6867 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
6868 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
6869 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
6870 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
6871 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
6872 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
6874 Cvar_RegisterVariable(&r_water);
6875 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
6876 Cvar_RegisterVariable(&r_water_clippingplanebias);
6877 Cvar_RegisterVariable(&r_water_refractdistort);
6878 Cvar_RegisterVariable(&r_water_reflectdistort);
6879 Cvar_RegisterVariable(&r_water_scissormode);
6880 Cvar_RegisterVariable(&r_lerpsprites);
6881 Cvar_RegisterVariable(&r_lerpmodels);
6882 Cvar_RegisterVariable(&r_lerplightstyles);
6883 Cvar_RegisterVariable(&r_waterscroll);
6884 Cvar_RegisterVariable(&r_bloom);
6885 Cvar_RegisterVariable(&r_bloom_colorscale);
6886 Cvar_RegisterVariable(&r_bloom_brighten);
6887 Cvar_RegisterVariable(&r_bloom_blur);
6888 Cvar_RegisterVariable(&r_bloom_resolution);
6889 Cvar_RegisterVariable(&r_bloom_colorexponent);
6890 Cvar_RegisterVariable(&r_bloom_colorsubtract);
6891 Cvar_RegisterVariable(&r_hdr);
6892 Cvar_RegisterVariable(&r_hdr_scenebrightness);
6893 Cvar_RegisterVariable(&r_hdr_glowintensity);
6894 Cvar_RegisterVariable(&r_hdr_range);
6895 Cvar_RegisterVariable(&r_hdr_irisadaptation);
6896 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
6897 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
6898 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
6899 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
6900 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
6901 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
6902 Cvar_RegisterVariable(&developer_texturelogging);
6903 Cvar_RegisterVariable(&gl_lightmaps);
6904 Cvar_RegisterVariable(&r_test);
6905 Cvar_RegisterVariable(&r_glsl_saturation);
6906 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
6907 Cvar_RegisterVariable(&r_framedatasize);
6908 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
6909 Cvar_SetValue("r_fullbrights", 0);
6910 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
6912 Cvar_RegisterVariable(&r_track_sprites);
6913 Cvar_RegisterVariable(&r_track_sprites_flags);
6914 Cvar_RegisterVariable(&r_track_sprites_scalew);
6915 Cvar_RegisterVariable(&r_track_sprites_scaleh);
6916 Cvar_RegisterVariable(&r_overheadsprites_perspective);
6917 Cvar_RegisterVariable(&r_overheadsprites_pushback);
6918 Cvar_RegisterVariable(&r_overheadsprites_scalex);
6919 Cvar_RegisterVariable(&r_overheadsprites_scaley);
6922 extern void R_Textures_Init(void);
6923 extern void GL_Draw_Init(void);
6924 extern void GL_Main_Init(void);
6925 extern void R_Shadow_Init(void);
6926 extern void R_Sky_Init(void);
6927 extern void GL_Surf_Init(void);
6928 extern void R_Particles_Init(void);
6929 extern void R_Explosion_Init(void);
6930 extern void gl_backend_init(void);
6931 extern void Sbar_Init(void);
6932 extern void R_LightningBeams_Init(void);
6933 extern void Mod_RenderInit(void);
6934 extern void Font_Init(void);
6936 void Render_Init(void)
6949 R_LightningBeams_Init();
6958 extern char *ENGINE_EXTENSIONS;
6961 gl_renderer = (const char *)qglGetString(GL_RENDERER);
6962 gl_vendor = (const char *)qglGetString(GL_VENDOR);
6963 gl_version = (const char *)qglGetString(GL_VERSION);
6964 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
6968 if (!gl_platformextensions)
6969 gl_platformextensions = "";
6971 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
6972 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
6973 Con_Printf("GL_VERSION: %s\n", gl_version);
6974 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
6975 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
6977 VID_CheckExtensions();
6979 // LordHavoc: report supported extensions
6980 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6982 // clear to black (loading plaque will be seen over this)
6983 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6986 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6990 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6992 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6995 p = r_refdef.view.frustum + i;
7000 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7004 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7008 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7012 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7016 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7020 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7024 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7028 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7036 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7040 for (i = 0;i < numplanes;i++)
7047 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7051 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7055 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7059 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7063 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7067 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7071 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7075 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7083 //==================================================================================
7085 // LordHavoc: this stores temporary data used within the same frame
7087 typedef struct r_framedata_mem_s
7089 struct r_framedata_mem_s *purge; // older mem block to free on next frame
7090 size_t size; // how much usable space
7091 size_t current; // how much space in use
7092 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
7093 size_t wantedsize; // how much space was allocated
7094 unsigned char *data; // start of real data (16byte aligned)
7098 static r_framedata_mem_t *r_framedata_mem;
7100 void R_FrameData_Reset(void)
7102 while (r_framedata_mem)
7104 r_framedata_mem_t *next = r_framedata_mem->purge;
7105 Mem_Free(r_framedata_mem);
7106 r_framedata_mem = next;
7110 void R_FrameData_Resize(void)
7113 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7114 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
7115 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
7117 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
7118 newmem->wantedsize = wantedsize;
7119 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
7120 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
7121 newmem->current = 0;
7123 newmem->purge = r_framedata_mem;
7124 r_framedata_mem = newmem;
7128 void R_FrameData_NewFrame(void)
7130 R_FrameData_Resize();
7131 if (!r_framedata_mem)
7133 // if we ran out of space on the last frame, free the old memory now
7134 while (r_framedata_mem->purge)
7136 // repeatedly remove the second item in the list, leaving only head
7137 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
7138 Mem_Free(r_framedata_mem->purge);
7139 r_framedata_mem->purge = next;
7141 // reset the current mem pointer
7142 r_framedata_mem->current = 0;
7143 r_framedata_mem->mark = 0;
7146 void *R_FrameData_Alloc(size_t size)
7150 // align to 16 byte boundary - the data pointer is already aligned, so we
7151 // only need to ensure the size of every allocation is also aligned
7152 size = (size + 15) & ~15;
7154 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
7156 // emergency - we ran out of space, allocate more memory
7157 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
7158 R_FrameData_Resize();
7161 data = r_framedata_mem->data + r_framedata_mem->current;
7162 r_framedata_mem->current += size;
7164 // count the usage for stats
7165 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
7166 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
7168 return (void *)data;
7171 void *R_FrameData_Store(size_t size, void *data)
7173 void *d = R_FrameData_Alloc(size);
7175 memcpy(d, data, size);
7179 void R_FrameData_SetMark(void)
7181 if (!r_framedata_mem)
7183 r_framedata_mem->mark = r_framedata_mem->current;
7186 void R_FrameData_ReturnToMark(void)
7188 if (!r_framedata_mem)
7190 r_framedata_mem->current = r_framedata_mem->mark;
7193 //==================================================================================
7195 // LordHavoc: animcache originally written by Echon, rewritten since then
7198 * Animation cache prevents re-generating mesh data for an animated model
7199 * multiple times in one frame for lighting, shadowing, reflections, etc.
7202 void R_AnimCache_Free(void)
7206 void R_AnimCache_ClearCache(void)
7209 entity_render_t *ent;
7211 for (i = 0;i < r_refdef.scene.numentities;i++)
7213 ent = r_refdef.scene.entities[i];
7214 ent->animcache_vertex3f = NULL;
7215 ent->animcache_normal3f = NULL;
7216 ent->animcache_svector3f = NULL;
7217 ent->animcache_tvector3f = NULL;
7218 ent->animcache_vertexmesh = NULL;
7219 ent->animcache_vertex3fbuffer = NULL;
7220 ent->animcache_vertexmeshbuffer = NULL;
7224 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7228 // check if we need the meshbuffers
7229 if (!vid.useinterleavedarrays)
7232 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7233 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7234 // TODO: upload vertex3f buffer?
7235 if (ent->animcache_vertexmesh)
7237 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7238 for (i = 0;i < numvertices;i++)
7239 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7240 if (ent->animcache_svector3f)
7241 for (i = 0;i < numvertices;i++)
7242 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7243 if (ent->animcache_tvector3f)
7244 for (i = 0;i < numvertices;i++)
7245 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7246 if (ent->animcache_normal3f)
7247 for (i = 0;i < numvertices;i++)
7248 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7249 // TODO: upload vertexmeshbuffer?
7253 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7255 dp_model_t *model = ent->model;
7257 // see if it's already cached this frame
7258 if (ent->animcache_vertex3f)
7260 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7261 if (wantnormals || wanttangents)
7263 if (ent->animcache_normal3f)
7264 wantnormals = false;
7265 if (ent->animcache_svector3f)
7266 wanttangents = false;
7267 if (wantnormals || wanttangents)
7269 numvertices = model->surfmesh.num_vertices;
7271 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7274 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7275 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7277 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7278 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7284 // see if this ent is worth caching
7285 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7287 // get some memory for this entity and generate mesh data
7288 numvertices = model->surfmesh.num_vertices;
7289 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7291 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7294 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7295 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7297 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7298 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7303 void R_AnimCache_CacheVisibleEntities(void)
7306 qboolean wantnormals = true;
7307 qboolean wanttangents = !r_showsurfaces.integer;
7309 switch(vid.renderpath)
7311 case RENDERPATH_GL20:
7312 case RENDERPATH_D3D9:
7313 case RENDERPATH_D3D10:
7314 case RENDERPATH_D3D11:
7315 case RENDERPATH_GLES2:
7317 case RENDERPATH_GL13:
7318 case RENDERPATH_GL11:
7319 wanttangents = false;
7321 case RENDERPATH_SOFT:
7325 if (r_shownormals.integer)
7326 wanttangents = wantnormals = true;
7328 // TODO: thread this
7329 // NOTE: R_PrepareRTLights() also caches entities
7331 for (i = 0;i < r_refdef.scene.numentities;i++)
7332 if (r_refdef.viewcache.entityvisible[i])
7333 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7336 //==================================================================================
7338 static void R_View_UpdateEntityLighting (void)
7341 entity_render_t *ent;
7342 vec3_t tempdiffusenormal, avg;
7343 vec_t f, fa, fd, fdd;
7344 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7346 for (i = 0;i < r_refdef.scene.numentities;i++)
7348 ent = r_refdef.scene.entities[i];
7350 // skip unseen models
7351 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7355 if (ent->model && ent->model->brush.num_leafs)
7357 // TODO: use modellight for r_ambient settings on world?
7358 VectorSet(ent->modellight_ambient, 0, 0, 0);
7359 VectorSet(ent->modellight_diffuse, 0, 0, 0);
7360 VectorSet(ent->modellight_lightdir, 0, 0, 1);
7364 // fetch the lighting from the worldmodel data
7365 VectorClear(ent->modellight_ambient);
7366 VectorClear(ent->modellight_diffuse);
7367 VectorClear(tempdiffusenormal);
7368 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7371 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7373 // complete lightning for lit sprites
7374 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
7375 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
7377 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
7378 org[2] = org[2] + r_overheadsprites_pushback.value;
7379 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
7382 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
7384 if(ent->flags & RENDER_EQUALIZE)
7386 // first fix up ambient lighting...
7387 if(r_equalize_entities_minambient.value > 0)
7389 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7392 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7393 if(fa < r_equalize_entities_minambient.value * fd)
7396 // fa'/fd' = minambient
7397 // fa'+0.25*fd' = fa+0.25*fd
7399 // fa' = fd' * minambient
7400 // fd'*(0.25+minambient) = fa+0.25*fd
7402 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7403 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7405 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7406 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
7407 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7408 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7413 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7415 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
7416 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7420 // adjust brightness and saturation to target
7421 avg[0] = avg[1] = avg[2] = fa / f;
7422 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
7423 avg[0] = avg[1] = avg[2] = fd / f;
7424 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
7430 VectorSet(ent->modellight_ambient, 1, 1, 1);
7432 // move the light direction into modelspace coordinates for lighting code
7433 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7434 if(VectorLength2(ent->modellight_lightdir) == 0)
7435 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7436 VectorNormalize(ent->modellight_lightdir);
7440 #define MAX_LINEOFSIGHTTRACES 64
7442 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7445 vec3_t boxmins, boxmaxs;
7448 dp_model_t *model = r_refdef.scene.worldmodel;
7450 if (!model || !model->brush.TraceLineOfSight)
7453 // expand the box a little
7454 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7455 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7456 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7457 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7458 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7459 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7461 // return true if eye is inside enlarged box
7462 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7466 VectorCopy(eye, start);
7467 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7468 if (model->brush.TraceLineOfSight(model, start, end))
7471 // try various random positions
7472 for (i = 0;i < numsamples;i++)
7474 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7475 if (model->brush.TraceLineOfSight(model, start, end))
7483 static void R_View_UpdateEntityVisible (void)
7488 entity_render_t *ent;
7490 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7491 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7492 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
7493 : RENDER_EXTERIORMODEL;
7494 if (!r_drawviewmodel.integer)
7495 renderimask |= RENDER_VIEWMODEL;
7496 if (!r_drawexteriormodel.integer)
7497 renderimask |= RENDER_EXTERIORMODEL;
7498 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
7500 // worldmodel can check visibility
7501 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
7502 for (i = 0;i < r_refdef.scene.numentities;i++)
7504 ent = r_refdef.scene.entities[i];
7505 if (!(ent->flags & renderimask))
7506 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)))
7507 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))
7508 r_refdef.viewcache.entityvisible[i] = true;
7510 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
7511 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
7513 for (i = 0;i < r_refdef.scene.numentities;i++)
7515 ent = r_refdef.scene.entities[i];
7516 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
7518 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
7520 continue; // temp entities do pvs only
7521 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
7522 ent->last_trace_visibility = realtime;
7523 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
7524 r_refdef.viewcache.entityvisible[i] = 0;
7531 // no worldmodel or it can't check visibility
7532 for (i = 0;i < r_refdef.scene.numentities;i++)
7534 ent = r_refdef.scene.entities[i];
7535 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));
7540 /// only used if skyrendermasked, and normally returns false
7541 int R_DrawBrushModelsSky (void)
7544 entity_render_t *ent;
7547 for (i = 0;i < r_refdef.scene.numentities;i++)
7549 if (!r_refdef.viewcache.entityvisible[i])
7551 ent = r_refdef.scene.entities[i];
7552 if (!ent->model || !ent->model->DrawSky)
7554 ent->model->DrawSky(ent);
7560 static void R_DrawNoModel(entity_render_t *ent);
7561 static void R_DrawModels(void)
7564 entity_render_t *ent;
7566 for (i = 0;i < r_refdef.scene.numentities;i++)
7568 if (!r_refdef.viewcache.entityvisible[i])
7570 ent = r_refdef.scene.entities[i];
7571 r_refdef.stats.entities++;
7572 if (ent->model && ent->model->Draw != NULL)
7573 ent->model->Draw(ent);
7579 static void R_DrawModelsDepth(void)
7582 entity_render_t *ent;
7584 for (i = 0;i < r_refdef.scene.numentities;i++)
7586 if (!r_refdef.viewcache.entityvisible[i])
7588 ent = r_refdef.scene.entities[i];
7589 if (ent->model && ent->model->DrawDepth != NULL)
7590 ent->model->DrawDepth(ent);
7594 static void R_DrawModelsDebug(void)
7597 entity_render_t *ent;
7599 for (i = 0;i < r_refdef.scene.numentities;i++)
7601 if (!r_refdef.viewcache.entityvisible[i])
7603 ent = r_refdef.scene.entities[i];
7604 if (ent->model && ent->model->DrawDebug != NULL)
7605 ent->model->DrawDebug(ent);
7609 static void R_DrawModelsAddWaterPlanes(void)
7612 entity_render_t *ent;
7614 for (i = 0;i < r_refdef.scene.numentities;i++)
7616 if (!r_refdef.viewcache.entityvisible[i])
7618 ent = r_refdef.scene.entities[i];
7619 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
7620 ent->model->DrawAddWaterPlanes(ent);
7624 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
7626 if (r_hdr_irisadaptation.integer)
7630 vec3_t diffusenormal;
7635 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
7636 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
7637 brightness = max(0.0000001f, brightness);
7638 goal = r_hdr_irisadaptation_multiplier.value / brightness;
7639 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
7640 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
7641 current = r_hdr_irisadaptation_value.value;
7643 current = min(current + adjust, goal);
7644 else if (current > goal)
7645 current = max(current - adjust, goal);
7646 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
7647 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
7649 else if (r_hdr_irisadaptation_value.value != 1.0f)
7650 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
7653 static void R_View_SetFrustum(const int *scissor)
7656 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
7657 vec3_t forward, left, up, origin, v;
7661 // flipped x coordinates (because x points left here)
7662 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
7663 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
7665 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
7666 switch(vid.renderpath)
7668 case RENDERPATH_D3D9:
7669 case RENDERPATH_D3D10:
7670 case RENDERPATH_D3D11:
7671 case RENDERPATH_SOFT:
7672 // non-flipped y coordinates
7673 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7674 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7676 case RENDERPATH_GL11:
7677 case RENDERPATH_GL13:
7678 case RENDERPATH_GL20:
7679 case RENDERPATH_GLES2:
7680 // non-flipped y coordinates
7681 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7682 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7687 // we can't trust r_refdef.view.forward and friends in reflected scenes
7688 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
7691 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
7692 r_refdef.view.frustum[0].normal[1] = 0 - 0;
7693 r_refdef.view.frustum[0].normal[2] = -1 - 0;
7694 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
7695 r_refdef.view.frustum[1].normal[1] = 0 + 0;
7696 r_refdef.view.frustum[1].normal[2] = -1 + 0;
7697 r_refdef.view.frustum[2].normal[0] = 0 - 0;
7698 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
7699 r_refdef.view.frustum[2].normal[2] = -1 - 0;
7700 r_refdef.view.frustum[3].normal[0] = 0 + 0;
7701 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
7702 r_refdef.view.frustum[3].normal[2] = -1 + 0;
7706 zNear = r_refdef.nearclip;
7707 nudge = 1.0 - 1.0 / (1<<23);
7708 r_refdef.view.frustum[4].normal[0] = 0 - 0;
7709 r_refdef.view.frustum[4].normal[1] = 0 - 0;
7710 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7711 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
7712 r_refdef.view.frustum[5].normal[0] = 0 + 0;
7713 r_refdef.view.frustum[5].normal[1] = 0 + 0;
7714 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7715 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7721 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
7722 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
7723 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
7724 r_refdef.view.frustum[0].dist = m[15] - m[12];
7726 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
7727 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
7728 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
7729 r_refdef.view.frustum[1].dist = m[15] + m[12];
7731 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
7732 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
7733 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
7734 r_refdef.view.frustum[2].dist = m[15] - m[13];
7736 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
7737 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
7738 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
7739 r_refdef.view.frustum[3].dist = m[15] + m[13];
7741 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
7742 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
7743 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
7744 r_refdef.view.frustum[4].dist = m[15] - m[14];
7746 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
7747 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
7748 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
7749 r_refdef.view.frustum[5].dist = m[15] + m[14];
7752 if (r_refdef.view.useperspective)
7754 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
7755 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]);
7756 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]);
7757 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]);
7758 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]);
7760 // then the normals from the corners relative to origin
7761 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
7762 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
7763 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
7764 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
7766 // in a NORMAL view, forward cross left == up
7767 // in a REFLECTED view, forward cross left == down
7768 // so our cross products above need to be adjusted for a left handed coordinate system
7769 CrossProduct(forward, left, v);
7770 if(DotProduct(v, up) < 0)
7772 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
7773 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
7774 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
7775 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
7778 // Leaving those out was a mistake, those were in the old code, and they
7779 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
7780 // I couldn't reproduce it after adding those normalizations. --blub
7781 VectorNormalize(r_refdef.view.frustum[0].normal);
7782 VectorNormalize(r_refdef.view.frustum[1].normal);
7783 VectorNormalize(r_refdef.view.frustum[2].normal);
7784 VectorNormalize(r_refdef.view.frustum[3].normal);
7786 // make the corners absolute
7787 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
7788 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
7789 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
7790 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
7793 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7795 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
7796 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
7797 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
7798 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
7799 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7803 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
7804 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
7805 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
7806 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
7807 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7808 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
7809 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
7810 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
7811 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
7812 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7814 r_refdef.view.numfrustumplanes = 5;
7816 if (r_refdef.view.useclipplane)
7818 r_refdef.view.numfrustumplanes = 6;
7819 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
7822 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7823 PlaneClassify(r_refdef.view.frustum + i);
7825 // LordHavoc: note to all quake engine coders, Quake had a special case
7826 // for 90 degrees which assumed a square view (wrong), so I removed it,
7827 // Quake2 has it disabled as well.
7829 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
7830 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
7831 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
7832 //PlaneClassify(&frustum[0]);
7834 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
7835 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
7836 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
7837 //PlaneClassify(&frustum[1]);
7839 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
7840 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
7841 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
7842 //PlaneClassify(&frustum[2]);
7844 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
7845 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
7846 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
7847 //PlaneClassify(&frustum[3]);
7850 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
7851 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
7852 //PlaneClassify(&frustum[4]);
7855 void R_View_UpdateWithScissor(const int *myscissor)
7857 R_Main_ResizeViewCache();
7858 R_View_SetFrustum(myscissor);
7859 R_View_WorldVisibility(r_refdef.view.useclipplane);
7860 R_View_UpdateEntityVisible();
7861 R_View_UpdateEntityLighting();
7864 void R_View_Update(void)
7866 R_Main_ResizeViewCache();
7867 R_View_SetFrustum(NULL);
7868 R_View_WorldVisibility(r_refdef.view.useclipplane);
7869 R_View_UpdateEntityVisible();
7870 R_View_UpdateEntityLighting();
7873 void R_SetupView(qboolean allowwaterclippingplane)
7875 const float *customclipplane = NULL;
7877 if (r_refdef.view.useclipplane && allowwaterclippingplane)
7879 // LordHavoc: couldn't figure out how to make this approach the
7880 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
7881 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
7882 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
7883 dist = r_refdef.view.clipplane.dist;
7884 plane[0] = r_refdef.view.clipplane.normal[0];
7885 plane[1] = r_refdef.view.clipplane.normal[1];
7886 plane[2] = r_refdef.view.clipplane.normal[2];
7888 customclipplane = plane;
7891 if (!r_refdef.view.useperspective)
7892 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);
7893 else if (vid.stencil && r_useinfinitefarclip.integer)
7894 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);
7896 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);
7897 R_SetViewport(&r_refdef.view.viewport);
7900 void R_EntityMatrix(const matrix4x4_t *matrix)
7902 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
7904 gl_modelmatrixchanged = false;
7905 gl_modelmatrix = *matrix;
7906 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
7907 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
7908 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
7909 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
7911 switch(vid.renderpath)
7913 case RENDERPATH_D3D9:
7915 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
7916 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
7919 case RENDERPATH_D3D10:
7920 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
7922 case RENDERPATH_D3D11:
7923 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
7925 case RENDERPATH_GL13:
7926 case RENDERPATH_GL11:
7927 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7929 case RENDERPATH_SOFT:
7930 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
7931 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
7933 case RENDERPATH_GL20:
7934 case RENDERPATH_GLES2:
7935 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
7936 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
7942 void R_ResetViewRendering2D(void)
7944 r_viewport_t viewport;
7947 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
7948 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);
7949 R_SetViewport(&viewport);
7950 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
7951 GL_Color(1, 1, 1, 1);
7952 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7953 GL_BlendFunc(GL_ONE, GL_ZERO);
7954 GL_ScissorTest(false);
7955 GL_DepthMask(false);
7956 GL_DepthRange(0, 1);
7957 GL_DepthTest(false);
7958 GL_DepthFunc(GL_LEQUAL);
7959 R_EntityMatrix(&identitymatrix);
7960 R_Mesh_ResetTextureState();
7961 GL_PolygonOffset(0, 0);
7962 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
7963 switch(vid.renderpath)
7965 case RENDERPATH_GL11:
7966 case RENDERPATH_GL13:
7967 case RENDERPATH_GL20:
7968 case RENDERPATH_GLES2:
7969 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7971 case RENDERPATH_D3D9:
7972 case RENDERPATH_D3D10:
7973 case RENDERPATH_D3D11:
7974 case RENDERPATH_SOFT:
7977 GL_CullFace(GL_NONE);
7980 void R_ResetViewRendering3D(void)
7985 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7986 GL_Color(1, 1, 1, 1);
7987 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7988 GL_BlendFunc(GL_ONE, GL_ZERO);
7989 GL_ScissorTest(true);
7991 GL_DepthRange(0, 1);
7993 GL_DepthFunc(GL_LEQUAL);
7994 R_EntityMatrix(&identitymatrix);
7995 R_Mesh_ResetTextureState();
7996 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7997 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
7998 switch(vid.renderpath)
8000 case RENDERPATH_GL11:
8001 case RENDERPATH_GL13:
8002 case RENDERPATH_GL20:
8003 case RENDERPATH_GLES2:
8004 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8006 case RENDERPATH_D3D9:
8007 case RENDERPATH_D3D10:
8008 case RENDERPATH_D3D11:
8009 case RENDERPATH_SOFT:
8012 GL_CullFace(r_refdef.view.cullface_back);
8017 R_RenderView_UpdateViewVectors
8020 static void R_RenderView_UpdateViewVectors(void)
8022 // break apart the view matrix into vectors for various purposes
8023 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8024 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8025 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8026 VectorNegate(r_refdef.view.left, r_refdef.view.right);
8027 // make an inverted copy of the view matrix for tracking sprites
8028 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8031 void R_RenderScene(void);
8032 void R_RenderWaterPlanes(void);
8034 static void R_Water_StartFrame(void)
8037 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8038 r_waterstate_waterplane_t *p;
8040 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8043 switch(vid.renderpath)
8045 case RENDERPATH_GL20:
8046 case RENDERPATH_D3D9:
8047 case RENDERPATH_D3D10:
8048 case RENDERPATH_D3D11:
8049 case RENDERPATH_SOFT:
8050 case RENDERPATH_GLES2:
8052 case RENDERPATH_GL13:
8053 case RENDERPATH_GL11:
8057 // set waterwidth and waterheight to the water resolution that will be
8058 // used (often less than the screen resolution for faster rendering)
8059 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8060 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8062 // calculate desired texture sizes
8063 // can't use water if the card does not support the texture size
8064 if (!r_water.integer || r_showsurfaces.integer)
8065 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8066 else if (vid.support.arb_texture_non_power_of_two)
8068 texturewidth = waterwidth;
8069 textureheight = waterheight;
8070 camerawidth = waterwidth;
8071 cameraheight = waterheight;
8075 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
8076 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
8077 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
8078 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
8081 // allocate textures as needed
8082 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8084 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8085 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8087 if (p->texture_refraction)
8088 R_FreeTexture(p->texture_refraction);
8089 p->texture_refraction = NULL;
8090 if (p->texture_reflection)
8091 R_FreeTexture(p->texture_reflection);
8092 p->texture_reflection = NULL;
8093 if (p->texture_camera)
8094 R_FreeTexture(p->texture_camera);
8095 p->texture_camera = NULL;
8097 memset(&r_waterstate, 0, sizeof(r_waterstate));
8098 r_waterstate.texturewidth = texturewidth;
8099 r_waterstate.textureheight = textureheight;
8100 r_waterstate.camerawidth = camerawidth;
8101 r_waterstate.cameraheight = cameraheight;
8104 if (r_waterstate.texturewidth)
8106 r_waterstate.enabled = true;
8108 // when doing a reduced render (HDR) we want to use a smaller area
8109 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8110 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8112 // set up variables that will be used in shader setup
8113 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8114 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8115 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8116 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8119 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8120 r_waterstate.numwaterplanes = 0;
8123 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8125 int triangleindex, planeindex;
8131 r_waterstate_waterplane_t *p;
8132 texture_t *t = R_GetCurrentTexture(surface->texture);
8134 // just use the first triangle with a valid normal for any decisions
8135 VectorClear(normal);
8136 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8138 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8139 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8140 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8141 TriangleNormal(vert[0], vert[1], vert[2], normal);
8142 if (VectorLength2(normal) >= 0.001)
8146 VectorCopy(normal, plane.normal);
8147 VectorNormalize(plane.normal);
8148 plane.dist = DotProduct(vert[0], plane.normal);
8149 PlaneClassify(&plane);
8150 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8152 // skip backfaces (except if nocullface is set)
8153 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8155 VectorNegate(plane.normal, plane.normal);
8157 PlaneClassify(&plane);
8161 // find a matching plane if there is one
8162 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8163 if(p->camera_entity == t->camera_entity)
8164 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8166 if (planeindex >= r_waterstate.maxwaterplanes)
8167 return; // nothing we can do, out of planes
8169 // if this triangle does not fit any known plane rendered this frame, add one
8170 if (planeindex >= r_waterstate.numwaterplanes)
8172 // store the new plane
8173 r_waterstate.numwaterplanes++;
8175 // clear materialflags and pvs
8176 p->materialflags = 0;
8177 p->pvsvalid = false;
8178 p->camera_entity = t->camera_entity;
8179 VectorCopy(surface->mins, p->mins);
8180 VectorCopy(surface->maxs, p->maxs);
8185 p->mins[0] = min(p->mins[0], surface->mins[0]);
8186 p->mins[1] = min(p->mins[1], surface->mins[1]);
8187 p->mins[2] = min(p->mins[2], surface->mins[2]);
8188 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8189 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8190 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8192 // merge this surface's materialflags into the waterplane
8193 p->materialflags |= t->currentmaterialflags;
8194 if(!(p->materialflags & MATERIALFLAG_CAMERA))
8196 // merge this surface's PVS into the waterplane
8197 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8198 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8199 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8201 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8207 static void R_Water_ProcessPlanes(void)
8210 r_refdef_view_t originalview;
8211 r_refdef_view_t myview;
8213 r_waterstate_waterplane_t *p;
8216 originalview = r_refdef.view;
8218 // make sure enough textures are allocated
8219 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8221 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8223 if (!p->texture_refraction)
8224 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);
8225 if (!p->texture_refraction)
8228 else if (p->materialflags & MATERIALFLAG_CAMERA)
8230 if (!p->texture_camera)
8231 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);
8232 if (!p->texture_camera)
8236 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8238 if (!p->texture_reflection)
8239 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);
8240 if (!p->texture_reflection)
8246 r_refdef.view = originalview;
8247 r_refdef.view.showdebug = false;
8248 r_refdef.view.width = r_waterstate.waterwidth;
8249 r_refdef.view.height = r_waterstate.waterheight;
8250 r_refdef.view.useclipplane = true;
8251 myview = r_refdef.view;
8252 r_waterstate.renderingscene = true;
8253 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8255 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8257 r_refdef.view = myview;
8258 if(r_water_scissormode.integer)
8261 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8262 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8265 // render reflected scene and copy into texture
8266 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8267 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8268 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8269 r_refdef.view.clipplane = p->plane;
8271 // reverse the cullface settings for this render
8272 r_refdef.view.cullface_front = GL_FRONT;
8273 r_refdef.view.cullface_back = GL_BACK;
8274 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8276 r_refdef.view.usecustompvs = true;
8278 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8280 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8283 R_ResetViewRendering3D();
8284 R_ClearScreen(r_refdef.fogenabled);
8285 if(r_water_scissormode.integer & 2)
8286 R_View_UpdateWithScissor(myscissor);
8289 if(r_water_scissormode.integer & 1)
8290 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8293 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);
8296 // render the normal view scene and copy into texture
8297 // (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)
8298 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8300 r_refdef.view = myview;
8301 if(r_water_scissormode.integer)
8304 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8305 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8308 r_waterstate.renderingrefraction = true;
8310 r_refdef.view.clipplane = p->plane;
8311 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8312 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8314 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8316 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8317 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8318 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8319 R_RenderView_UpdateViewVectors();
8320 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8322 r_refdef.view.usecustompvs = true;
8323 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);
8327 PlaneClassify(&r_refdef.view.clipplane);
8329 R_ResetViewRendering3D();
8330 R_ClearScreen(r_refdef.fogenabled);
8331 if(r_water_scissormode.integer & 2)
8332 R_View_UpdateWithScissor(myscissor);
8335 if(r_water_scissormode.integer & 1)
8336 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8339 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);
8340 r_waterstate.renderingrefraction = false;
8342 else if (p->materialflags & MATERIALFLAG_CAMERA)
8344 r_refdef.view = myview;
8346 r_refdef.view.clipplane = p->plane;
8347 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8348 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8350 r_refdef.view.width = r_waterstate.camerawidth;
8351 r_refdef.view.height = r_waterstate.cameraheight;
8352 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8353 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8355 if(p->camera_entity)
8357 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8358 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8361 // note: all of the view is used for displaying... so
8362 // there is no use in scissoring
8364 // reverse the cullface settings for this render
8365 r_refdef.view.cullface_front = GL_FRONT;
8366 r_refdef.view.cullface_back = GL_BACK;
8367 // also reverse the view matrix
8368 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
8369 R_RenderView_UpdateViewVectors();
8370 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8372 r_refdef.view.usecustompvs = true;
8373 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);
8376 // camera needs no clipplane
8377 r_refdef.view.useclipplane = false;
8379 PlaneClassify(&r_refdef.view.clipplane);
8381 R_ResetViewRendering3D();
8382 R_ClearScreen(r_refdef.fogenabled);
8386 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);
8387 r_waterstate.renderingrefraction = false;
8391 r_waterstate.renderingscene = false;
8392 r_refdef.view = originalview;
8393 R_ResetViewRendering3D();
8394 R_ClearScreen(r_refdef.fogenabled);
8398 r_refdef.view = originalview;
8399 r_waterstate.renderingscene = false;
8400 Cvar_SetValueQuick(&r_water, 0);
8401 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
8405 void R_Bloom_StartFrame(void)
8407 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8409 switch(vid.renderpath)
8411 case RENDERPATH_GL20:
8412 case RENDERPATH_D3D9:
8413 case RENDERPATH_D3D10:
8414 case RENDERPATH_D3D11:
8415 case RENDERPATH_SOFT:
8416 case RENDERPATH_GLES2:
8418 case RENDERPATH_GL13:
8419 case RENDERPATH_GL11:
8423 // set bloomwidth and bloomheight to the bloom resolution that will be
8424 // used (often less than the screen resolution for faster rendering)
8425 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8426 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8427 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8428 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8429 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8431 // calculate desired texture sizes
8432 if (vid.support.arb_texture_non_power_of_two)
8434 screentexturewidth = r_refdef.view.width;
8435 screentextureheight = r_refdef.view.height;
8436 bloomtexturewidth = r_bloomstate.bloomwidth;
8437 bloomtextureheight = r_bloomstate.bloomheight;
8441 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
8442 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
8443 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
8444 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
8447 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))
8449 Cvar_SetValueQuick(&r_hdr, 0);
8450 Cvar_SetValueQuick(&r_bloom, 0);
8451 Cvar_SetValueQuick(&r_motionblur, 0);
8452 Cvar_SetValueQuick(&r_damageblur, 0);
8455 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)))
8456 screentexturewidth = screentextureheight = 0;
8457 if (!r_hdr.integer && !r_bloom.integer)
8458 bloomtexturewidth = bloomtextureheight = 0;
8460 // allocate textures as needed
8461 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8463 if (r_bloomstate.texture_screen)
8464 R_FreeTexture(r_bloomstate.texture_screen);
8465 r_bloomstate.texture_screen = NULL;
8466 r_bloomstate.screentexturewidth = screentexturewidth;
8467 r_bloomstate.screentextureheight = screentextureheight;
8468 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8469 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);
8471 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8473 if (r_bloomstate.texture_bloom)
8474 R_FreeTexture(r_bloomstate.texture_bloom);
8475 r_bloomstate.texture_bloom = NULL;
8476 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8477 r_bloomstate.bloomtextureheight = bloomtextureheight;
8478 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8479 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);
8482 // when doing a reduced render (HDR) we want to use a smaller area
8483 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8484 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8485 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8486 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8487 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8489 // set up a texcoord array for the full resolution screen image
8490 // (we have to keep this around to copy back during final render)
8491 r_bloomstate.screentexcoord2f[0] = 0;
8492 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
8493 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
8494 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
8495 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
8496 r_bloomstate.screentexcoord2f[5] = 0;
8497 r_bloomstate.screentexcoord2f[6] = 0;
8498 r_bloomstate.screentexcoord2f[7] = 0;
8500 // set up a texcoord array for the reduced resolution bloom image
8501 // (which will be additive blended over the screen image)
8502 r_bloomstate.bloomtexcoord2f[0] = 0;
8503 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8504 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8505 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8506 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8507 r_bloomstate.bloomtexcoord2f[5] = 0;
8508 r_bloomstate.bloomtexcoord2f[6] = 0;
8509 r_bloomstate.bloomtexcoord2f[7] = 0;
8511 switch(vid.renderpath)
8513 case RENDERPATH_GL11:
8514 case RENDERPATH_GL13:
8515 case RENDERPATH_GL20:
8516 case RENDERPATH_SOFT:
8517 case RENDERPATH_GLES2:
8519 case RENDERPATH_D3D9:
8520 case RENDERPATH_D3D10:
8521 case RENDERPATH_D3D11:
8524 for (i = 0;i < 4;i++)
8526 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
8527 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
8528 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
8529 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
8535 if (r_hdr.integer || r_bloom.integer)
8537 r_bloomstate.enabled = true;
8538 r_bloomstate.hdr = r_hdr.integer != 0;
8541 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);
8544 void R_Bloom_CopyBloomTexture(float colorscale)
8546 r_refdef.stats.bloom++;
8548 // scale down screen texture to the bloom texture size
8550 R_SetViewport(&r_bloomstate.viewport);
8551 GL_BlendFunc(GL_ONE, GL_ZERO);
8552 GL_Color(colorscale, colorscale, colorscale, 1);
8553 // 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...
8554 switch(vid.renderpath)
8556 case RENDERPATH_GL11:
8557 case RENDERPATH_GL13:
8558 case RENDERPATH_GL20:
8559 case RENDERPATH_SOFT:
8560 case RENDERPATH_GLES2:
8561 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8563 case RENDERPATH_D3D9:
8564 case RENDERPATH_D3D10:
8565 case RENDERPATH_D3D11:
8566 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8569 // TODO: do boxfilter scale-down in shader?
8570 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8571 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8572 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8574 // we now have a bloom image in the framebuffer
8575 // copy it into the bloom image texture for later processing
8576 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);
8577 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8580 void R_Bloom_CopyHDRTexture(void)
8582 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);
8583 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8586 void R_Bloom_MakeTexture(void)
8589 float xoffset, yoffset, r, brighten;
8591 r_refdef.stats.bloom++;
8593 R_ResetViewRendering2D();
8595 // we have a bloom image in the framebuffer
8597 R_SetViewport(&r_bloomstate.viewport);
8599 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
8602 r = bound(0, r_bloom_colorexponent.value / x, 1);
8603 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
8605 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
8606 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8607 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8608 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8610 // copy the vertically blurred bloom view to a texture
8611 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);
8612 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8615 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
8616 brighten = r_bloom_brighten.value;
8618 brighten *= r_hdr_range.value;
8619 brighten = sqrt(brighten);
8621 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
8622 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8624 for (dir = 0;dir < 2;dir++)
8626 // blend on at multiple vertical offsets to achieve a vertical blur
8627 // TODO: do offset blends using GLSL
8628 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
8629 GL_BlendFunc(GL_ONE, GL_ZERO);
8630 for (x = -range;x <= range;x++)
8632 if (!dir){xoffset = 0;yoffset = x;}
8633 else {xoffset = x;yoffset = 0;}
8634 xoffset /= (float)r_bloomstate.bloomtexturewidth;
8635 yoffset /= (float)r_bloomstate.bloomtextureheight;
8636 // compute a texcoord array with the specified x and y offset
8637 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
8638 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8639 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8640 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8641 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8642 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
8643 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
8644 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
8645 // this r value looks like a 'dot' particle, fading sharply to
8646 // black at the edges
8647 // (probably not realistic but looks good enough)
8648 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
8649 //r = brighten/(range*2+1);
8650 r = brighten / (range * 2 + 1);
8652 r *= (1 - x*x/(float)(range*range));
8653 GL_Color(r, r, r, 1);
8654 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
8655 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8656 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8657 GL_BlendFunc(GL_ONE, GL_ONE);
8660 // copy the vertically blurred bloom view to a texture
8661 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);
8662 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8666 void R_HDR_RenderBloomTexture(void)
8668 int oldwidth, oldheight;
8669 float oldcolorscale;
8670 qboolean oldwaterstate;
8672 oldwaterstate = r_waterstate.enabled;
8673 oldcolorscale = r_refdef.view.colorscale;
8674 oldwidth = r_refdef.view.width;
8675 oldheight = r_refdef.view.height;
8676 r_refdef.view.width = r_bloomstate.bloomwidth;
8677 r_refdef.view.height = r_bloomstate.bloomheight;
8679 if(r_hdr.integer < 2)
8680 r_waterstate.enabled = false;
8682 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
8683 // TODO: add exposure compensation features
8684 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
8686 r_refdef.view.showdebug = false;
8687 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
8689 R_ResetViewRendering3D();
8691 R_ClearScreen(r_refdef.fogenabled);
8692 if (r_timereport_active)
8693 R_TimeReport("HDRclear");
8696 if (r_timereport_active)
8697 R_TimeReport("visibility");
8699 // only do secondary renders with HDR if r_hdr is 2 or higher
8700 r_waterstate.numwaterplanes = 0;
8701 if (r_waterstate.enabled)
8702 R_RenderWaterPlanes();
8704 r_refdef.view.showdebug = true;
8706 r_waterstate.numwaterplanes = 0;
8708 R_ResetViewRendering2D();
8710 R_Bloom_CopyHDRTexture();
8711 R_Bloom_MakeTexture();
8713 // restore the view settings
8714 r_waterstate.enabled = oldwaterstate;
8715 r_refdef.view.width = oldwidth;
8716 r_refdef.view.height = oldheight;
8717 r_refdef.view.colorscale = oldcolorscale;
8719 R_ResetViewRendering3D();
8721 R_ClearScreen(r_refdef.fogenabled);
8722 if (r_timereport_active)
8723 R_TimeReport("viewclear");
8726 static void R_BlendView(void)
8728 unsigned int permutation;
8729 float uservecs[4][4];
8731 switch (vid.renderpath)
8733 case RENDERPATH_GL20:
8734 case RENDERPATH_D3D9:
8735 case RENDERPATH_D3D10:
8736 case RENDERPATH_D3D11:
8737 case RENDERPATH_SOFT:
8738 case RENDERPATH_GLES2:
8740 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
8741 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
8742 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
8743 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
8744 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
8746 if (r_bloomstate.texture_screen)
8748 // make sure the buffer is available
8749 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
8751 R_ResetViewRendering2D();
8753 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
8755 // declare variables
8757 static float avgspeed;
8759 speed = VectorLength(cl.movement_velocity);
8761 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
8762 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
8764 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
8765 speed = bound(0, speed, 1);
8766 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
8768 // calculate values into a standard alpha
8769 cl.motionbluralpha = 1 - exp(-
8771 (r_motionblur.value * speed / 80)
8773 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
8776 max(0.0001, cl.time - cl.oldtime) // fps independent
8779 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
8780 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
8782 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
8784 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8785 GL_Color(1, 1, 1, cl.motionbluralpha);
8786 switch(vid.renderpath)
8788 case RENDERPATH_GL11:
8789 case RENDERPATH_GL13:
8790 case RENDERPATH_GL20:
8791 case RENDERPATH_SOFT:
8792 case RENDERPATH_GLES2:
8793 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8795 case RENDERPATH_D3D9:
8796 case RENDERPATH_D3D10:
8797 case RENDERPATH_D3D11:
8798 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8801 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8802 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8803 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8807 // copy view into the screen texture
8808 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);
8809 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8811 else if (!r_bloomstate.texture_bloom)
8813 // we may still have to do view tint...
8814 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8816 // apply a color tint to the whole view
8817 R_ResetViewRendering2D();
8818 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8819 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
8820 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8821 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8822 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8824 break; // no screen processing, no bloom, skip it
8827 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
8829 // render simple bloom effect
8830 // copy the screen and shrink it and darken it for the bloom process
8831 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
8832 // make the bloom texture
8833 R_Bloom_MakeTexture();
8836 #if _MSC_VER >= 1400
8837 #define sscanf sscanf_s
8839 memset(uservecs, 0, sizeof(uservecs));
8840 if (r_glsl_postprocess_uservec1_enable.integer)
8841 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
8842 if (r_glsl_postprocess_uservec2_enable.integer)
8843 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
8844 if (r_glsl_postprocess_uservec3_enable.integer)
8845 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
8846 if (r_glsl_postprocess_uservec4_enable.integer)
8847 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
8849 R_ResetViewRendering2D();
8850 GL_Color(1, 1, 1, 1);
8851 GL_BlendFunc(GL_ONE, GL_ZERO);
8853 switch(vid.renderpath)
8855 case RENDERPATH_GL20:
8856 case RENDERPATH_GLES2:
8857 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8858 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
8859 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
8860 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
8861 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
8862 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]);
8863 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8864 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]);
8865 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]);
8866 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]);
8867 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]);
8868 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
8869 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8870 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);
8872 case RENDERPATH_D3D9:
8874 // 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...
8875 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8876 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
8877 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
8878 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
8879 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
8880 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8881 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8882 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
8883 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
8884 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
8885 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
8886 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
8887 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
8888 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
8891 case RENDERPATH_D3D10:
8892 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
8894 case RENDERPATH_D3D11:
8895 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
8897 case RENDERPATH_SOFT:
8898 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8899 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
8900 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
8901 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
8902 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
8903 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8904 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8905 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
8906 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
8907 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
8908 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
8909 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
8910 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8911 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
8916 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8917 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8919 case RENDERPATH_GL13:
8920 case RENDERPATH_GL11:
8921 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8923 // apply a color tint to the whole view
8924 R_ResetViewRendering2D();
8925 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8926 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
8927 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8928 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8929 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8935 matrix4x4_t r_waterscrollmatrix;
8937 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
8939 if (r_refdef.fog_density)
8941 r_refdef.fogcolor[0] = r_refdef.fog_red;
8942 r_refdef.fogcolor[1] = r_refdef.fog_green;
8943 r_refdef.fogcolor[2] = r_refdef.fog_blue;
8945 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
8946 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
8947 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
8948 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
8952 VectorCopy(r_refdef.fogcolor, fogvec);
8953 // color.rgb *= ContrastBoost * SceneBrightness;
8954 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
8955 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
8956 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
8957 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
8962 void R_UpdateVariables(void)
8966 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
8968 r_refdef.farclip = r_farclip_base.value;
8969 if (r_refdef.scene.worldmodel)
8970 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
8971 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
8973 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
8974 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
8975 r_refdef.polygonfactor = 0;
8976 r_refdef.polygonoffset = 0;
8977 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8978 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8980 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
8981 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
8982 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
8983 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
8984 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
8985 if (FAKELIGHT_ENABLED)
8987 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
8989 if (r_showsurfaces.integer)
8991 r_refdef.scene.rtworld = false;
8992 r_refdef.scene.rtworldshadows = false;
8993 r_refdef.scene.rtdlight = false;
8994 r_refdef.scene.rtdlightshadows = false;
8995 r_refdef.lightmapintensity = 0;
8998 if (gamemode == GAME_NEHAHRA)
9000 if (gl_fogenable.integer)
9002 r_refdef.oldgl_fogenable = true;
9003 r_refdef.fog_density = gl_fogdensity.value;
9004 r_refdef.fog_red = gl_fogred.value;
9005 r_refdef.fog_green = gl_foggreen.value;
9006 r_refdef.fog_blue = gl_fogblue.value;
9007 r_refdef.fog_alpha = 1;
9008 r_refdef.fog_start = 0;
9009 r_refdef.fog_end = gl_skyclip.value;
9010 r_refdef.fog_height = 1<<30;
9011 r_refdef.fog_fadedepth = 128;
9013 else if (r_refdef.oldgl_fogenable)
9015 r_refdef.oldgl_fogenable = false;
9016 r_refdef.fog_density = 0;
9017 r_refdef.fog_red = 0;
9018 r_refdef.fog_green = 0;
9019 r_refdef.fog_blue = 0;
9020 r_refdef.fog_alpha = 0;
9021 r_refdef.fog_start = 0;
9022 r_refdef.fog_end = 0;
9023 r_refdef.fog_height = 1<<30;
9024 r_refdef.fog_fadedepth = 128;
9028 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9029 r_refdef.fog_start = max(0, r_refdef.fog_start);
9030 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9032 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9034 if (r_refdef.fog_density && r_drawfog.integer)
9036 r_refdef.fogenabled = true;
9037 // this is the point where the fog reaches 0.9986 alpha, which we
9038 // consider a good enough cutoff point for the texture
9039 // (0.9986 * 256 == 255.6)
9040 if (r_fog_exp2.integer)
9041 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9043 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9044 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9045 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9046 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9047 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9048 R_BuildFogHeightTexture();
9049 // fog color was already set
9050 // update the fog texture
9051 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)
9052 R_BuildFogTexture();
9053 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9054 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9057 r_refdef.fogenabled = false;
9059 switch(vid.renderpath)
9061 case RENDERPATH_GL20:
9062 case RENDERPATH_D3D9:
9063 case RENDERPATH_D3D10:
9064 case RENDERPATH_D3D11:
9065 case RENDERPATH_SOFT:
9066 case RENDERPATH_GLES2:
9067 if(v_glslgamma.integer && !vid_gammatables_trivial)
9069 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9071 // build GLSL gamma texture
9072 #define RAMPWIDTH 256
9073 unsigned short ramp[RAMPWIDTH * 3];
9074 unsigned char rampbgr[RAMPWIDTH][4];
9077 r_texture_gammaramps_serial = vid_gammatables_serial;
9079 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9080 for(i = 0; i < RAMPWIDTH; ++i)
9082 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9083 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9084 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9087 if (r_texture_gammaramps)
9089 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
9093 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9099 // remove GLSL gamma texture
9102 case RENDERPATH_GL13:
9103 case RENDERPATH_GL11:
9108 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9109 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9115 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9116 if( scenetype != r_currentscenetype ) {
9117 // store the old scenetype
9118 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9119 r_currentscenetype = scenetype;
9120 // move in the new scene
9121 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9130 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9132 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9133 if( scenetype == r_currentscenetype ) {
9134 return &r_refdef.scene;
9136 return &r_scenes_store[ scenetype ];
9145 int dpsoftrast_test;
9146 void R_RenderView(void)
9148 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
9150 dpsoftrast_test = r_test.integer;
9152 if (r_timereport_active)
9153 R_TimeReport("start");
9154 r_textureframe++; // used only by R_GetCurrentTexture
9155 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9157 if(R_CompileShader_CheckStaticParms())
9160 if (!r_drawentities.integer)
9161 r_refdef.scene.numentities = 0;
9163 R_AnimCache_ClearCache();
9164 R_FrameData_NewFrame();
9166 /* adjust for stereo display */
9167 if(R_Stereo_Active())
9169 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);
9170 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
9173 if (r_refdef.view.isoverlay)
9175 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9176 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9177 R_TimeReport("depthclear");
9179 r_refdef.view.showdebug = false;
9181 r_waterstate.enabled = false;
9182 r_waterstate.numwaterplanes = 0;
9186 r_refdef.view.matrix = originalmatrix;
9192 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9194 r_refdef.view.matrix = originalmatrix;
9195 return; //Host_Error ("R_RenderView: NULL worldmodel");
9198 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
9200 R_RenderView_UpdateViewVectors();
9202 R_Shadow_UpdateWorldLightSelection();
9204 R_Bloom_StartFrame();
9205 R_Water_StartFrame();
9208 if (r_timereport_active)
9209 R_TimeReport("viewsetup");
9211 R_ResetViewRendering3D();
9213 if (r_refdef.view.clear || r_refdef.fogenabled)
9215 R_ClearScreen(r_refdef.fogenabled);
9216 if (r_timereport_active)
9217 R_TimeReport("viewclear");
9219 r_refdef.view.clear = true;
9221 // this produces a bloom texture to be used in R_BlendView() later
9222 if (r_hdr.integer && r_bloomstate.bloomwidth)
9224 R_HDR_RenderBloomTexture();
9225 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9226 r_textureframe++; // used only by R_GetCurrentTexture
9229 r_refdef.view.showdebug = true;
9232 if (r_timereport_active)
9233 R_TimeReport("visibility");
9235 r_waterstate.numwaterplanes = 0;
9236 if (r_waterstate.enabled)
9237 R_RenderWaterPlanes();
9240 r_waterstate.numwaterplanes = 0;
9243 if (r_timereport_active)
9244 R_TimeReport("blendview");
9246 GL_Scissor(0, 0, vid.width, vid.height);
9247 GL_ScissorTest(false);
9249 r_refdef.view.matrix = originalmatrix;
9254 void R_RenderWaterPlanes(void)
9256 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9258 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9259 if (r_timereport_active)
9260 R_TimeReport("waterworld");
9263 // don't let sound skip if going slow
9264 if (r_refdef.scene.extraupdate)
9267 R_DrawModelsAddWaterPlanes();
9268 if (r_timereport_active)
9269 R_TimeReport("watermodels");
9271 if (r_waterstate.numwaterplanes)
9273 R_Water_ProcessPlanes();
9274 if (r_timereport_active)
9275 R_TimeReport("waterscenes");
9279 extern void R_DrawLightningBeams (void);
9280 extern void VM_CL_AddPolygonsToMeshQueue (void);
9281 extern void R_DrawPortals (void);
9282 extern cvar_t cl_locs_show;
9283 static void R_DrawLocs(void);
9284 static void R_DrawEntityBBoxes(void);
9285 static void R_DrawModelDecals(void);
9286 extern void R_DrawModelShadows(void);
9287 extern void R_DrawModelShadowMaps(void);
9288 extern cvar_t cl_decals_newsystem;
9289 extern qboolean r_shadow_usingdeferredprepass;
9290 void R_RenderScene(void)
9292 qboolean shadowmapping = false;
9294 if (r_timereport_active)
9295 R_TimeReport("beginscene");
9297 r_refdef.stats.renders++;
9301 // don't let sound skip if going slow
9302 if (r_refdef.scene.extraupdate)
9305 R_MeshQueue_BeginScene();
9309 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);
9311 if (r_timereport_active)
9312 R_TimeReport("skystartframe");
9314 if (cl.csqc_vidvars.drawworld)
9316 // don't let sound skip if going slow
9317 if (r_refdef.scene.extraupdate)
9320 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9322 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9323 if (r_timereport_active)
9324 R_TimeReport("worldsky");
9327 if (R_DrawBrushModelsSky() && r_timereport_active)
9328 R_TimeReport("bmodelsky");
9330 if (skyrendermasked && skyrenderlater)
9332 // we have to force off the water clipping plane while rendering sky
9336 if (r_timereport_active)
9337 R_TimeReport("sky");
9341 R_AnimCache_CacheVisibleEntities();
9342 if (r_timereport_active)
9343 R_TimeReport("animation");
9345 R_Shadow_PrepareLights();
9346 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9347 R_Shadow_PrepareModelShadows();
9348 if (r_timereport_active)
9349 R_TimeReport("preparelights");
9351 if (R_Shadow_ShadowMappingEnabled())
9352 shadowmapping = true;
9354 if (r_shadow_usingdeferredprepass)
9355 R_Shadow_DrawPrepass();
9357 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9359 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9360 if (r_timereport_active)
9361 R_TimeReport("worlddepth");
9363 if (r_depthfirst.integer >= 2)
9365 R_DrawModelsDepth();
9366 if (r_timereport_active)
9367 R_TimeReport("modeldepth");
9370 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9372 R_DrawModelShadowMaps();
9373 R_ResetViewRendering3D();
9374 // don't let sound skip if going slow
9375 if (r_refdef.scene.extraupdate)
9379 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9381 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9382 if (r_timereport_active)
9383 R_TimeReport("world");
9386 // don't let sound skip if going slow
9387 if (r_refdef.scene.extraupdate)
9391 if (r_timereport_active)
9392 R_TimeReport("models");
9394 // don't let sound skip if going slow
9395 if (r_refdef.scene.extraupdate)
9398 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9400 R_DrawModelShadows();
9401 R_ResetViewRendering3D();
9402 // don't let sound skip if going slow
9403 if (r_refdef.scene.extraupdate)
9407 if (!r_shadow_usingdeferredprepass)
9409 R_Shadow_DrawLights();
9410 if (r_timereport_active)
9411 R_TimeReport("rtlights");
9414 // don't let sound skip if going slow
9415 if (r_refdef.scene.extraupdate)
9418 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9420 R_DrawModelShadows();
9421 R_ResetViewRendering3D();
9422 // don't let sound skip if going slow
9423 if (r_refdef.scene.extraupdate)
9427 if (cl.csqc_vidvars.drawworld)
9429 if (cl_decals_newsystem.integer)
9431 R_DrawModelDecals();
9432 if (r_timereport_active)
9433 R_TimeReport("modeldecals");
9438 if (r_timereport_active)
9439 R_TimeReport("decals");
9443 if (r_timereport_active)
9444 R_TimeReport("particles");
9447 if (r_timereport_active)
9448 R_TimeReport("explosions");
9450 R_DrawLightningBeams();
9451 if (r_timereport_active)
9452 R_TimeReport("lightning");
9455 VM_CL_AddPolygonsToMeshQueue();
9457 if (r_refdef.view.showdebug)
9459 if (cl_locs_show.integer)
9462 if (r_timereport_active)
9463 R_TimeReport("showlocs");
9466 if (r_drawportals.integer)
9469 if (r_timereport_active)
9470 R_TimeReport("portals");
9473 if (r_showbboxes.value > 0)
9475 R_DrawEntityBBoxes();
9476 if (r_timereport_active)
9477 R_TimeReport("bboxes");
9481 R_MeshQueue_RenderTransparent();
9482 if (r_timereport_active)
9483 R_TimeReport("drawtrans");
9485 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))
9487 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9488 if (r_timereport_active)
9489 R_TimeReport("worlddebug");
9490 R_DrawModelsDebug();
9491 if (r_timereport_active)
9492 R_TimeReport("modeldebug");
9495 if (cl.csqc_vidvars.drawworld)
9497 R_Shadow_DrawCoronas();
9498 if (r_timereport_active)
9499 R_TimeReport("coronas");
9504 GL_DepthTest(false);
9505 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9506 GL_Color(1, 1, 1, 1);
9507 qglBegin(GL_POLYGON);
9508 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
9509 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
9510 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
9511 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
9513 qglBegin(GL_POLYGON);
9514 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]);
9515 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]);
9516 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]);
9517 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]);
9519 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9523 // don't let sound skip if going slow
9524 if (r_refdef.scene.extraupdate)
9527 R_ResetViewRendering2D();
9530 static const unsigned short bboxelements[36] =
9540 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9543 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9545 RSurf_ActiveWorldEntity();
9547 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9548 GL_DepthMask(false);
9549 GL_DepthRange(0, 1);
9550 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9551 // R_Mesh_ResetTextureState();
9553 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9554 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9555 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9556 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9557 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9558 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9559 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9560 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9561 R_FillColors(color4f, 8, cr, cg, cb, ca);
9562 if (r_refdef.fogenabled)
9564 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9566 f1 = RSurf_FogVertex(v);
9568 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9569 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9570 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9573 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
9574 R_Mesh_ResetTextureState();
9575 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9576 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
9579 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9583 prvm_edict_t *edict;
9584 prvm_prog_t *prog_save = prog;
9586 // this function draws bounding boxes of server entities
9590 GL_CullFace(GL_NONE);
9591 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9595 for (i = 0;i < numsurfaces;i++)
9597 edict = PRVM_EDICT_NUM(surfacelist[i]);
9598 switch ((int)edict->fields.server->solid)
9600 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
9601 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
9602 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
9603 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9604 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
9605 default: Vector4Set(color, 0, 0, 0, 0.50);break;
9607 color[3] *= r_showbboxes.value;
9608 color[3] = bound(0, color[3], 1);
9609 GL_DepthTest(!r_showdisabledepthtest.integer);
9610 GL_CullFace(r_refdef.view.cullface_front);
9611 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
9617 static void R_DrawEntityBBoxes(void)
9620 prvm_edict_t *edict;
9622 prvm_prog_t *prog_save = prog;
9624 // this function draws bounding boxes of server entities
9630 for (i = 0;i < prog->num_edicts;i++)
9632 edict = PRVM_EDICT_NUM(i);
9633 if (edict->priv.server->free)
9635 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
9636 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
9638 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
9640 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
9641 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
9647 static const int nomodelelement3i[24] =
9659 static const unsigned short nomodelelement3s[24] =
9671 static const float nomodelvertex3f[6*3] =
9681 static const float nomodelcolor4f[6*4] =
9683 0.0f, 0.0f, 0.5f, 1.0f,
9684 0.0f, 0.0f, 0.5f, 1.0f,
9685 0.0f, 0.5f, 0.0f, 1.0f,
9686 0.0f, 0.5f, 0.0f, 1.0f,
9687 0.5f, 0.0f, 0.0f, 1.0f,
9688 0.5f, 0.0f, 0.0f, 1.0f
9691 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9697 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);
9699 // this is only called once per entity so numsurfaces is always 1, and
9700 // surfacelist is always {0}, so this code does not handle batches
9702 if (rsurface.ent_flags & RENDER_ADDITIVE)
9704 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
9705 GL_DepthMask(false);
9707 else if (rsurface.colormod[3] < 1)
9709 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9710 GL_DepthMask(false);
9714 GL_BlendFunc(GL_ONE, GL_ZERO);
9717 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
9718 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
9719 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
9720 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
9721 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
9722 for (i = 0, c = color4f;i < 6;i++, c += 4)
9724 c[0] *= rsurface.colormod[0];
9725 c[1] *= rsurface.colormod[1];
9726 c[2] *= rsurface.colormod[2];
9727 c[3] *= rsurface.colormod[3];
9729 if (r_refdef.fogenabled)
9731 for (i = 0, c = color4f;i < 6;i++, c += 4)
9733 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
9735 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
9736 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
9737 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
9740 // R_Mesh_ResetTextureState();
9741 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9742 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
9743 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
9746 void R_DrawNoModel(entity_render_t *ent)
9749 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
9750 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
9751 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
9753 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
9756 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
9758 vec3_t right1, right2, diff, normal;
9760 VectorSubtract (org2, org1, normal);
9762 // calculate 'right' vector for start
9763 VectorSubtract (r_refdef.view.origin, org1, diff);
9764 CrossProduct (normal, diff, right1);
9765 VectorNormalize (right1);
9767 // calculate 'right' vector for end
9768 VectorSubtract (r_refdef.view.origin, org2, diff);
9769 CrossProduct (normal, diff, right2);
9770 VectorNormalize (right2);
9772 vert[ 0] = org1[0] + width * right1[0];
9773 vert[ 1] = org1[1] + width * right1[1];
9774 vert[ 2] = org1[2] + width * right1[2];
9775 vert[ 3] = org1[0] - width * right1[0];
9776 vert[ 4] = org1[1] - width * right1[1];
9777 vert[ 5] = org1[2] - width * right1[2];
9778 vert[ 6] = org2[0] - width * right2[0];
9779 vert[ 7] = org2[1] - width * right2[1];
9780 vert[ 8] = org2[2] - width * right2[2];
9781 vert[ 9] = org2[0] + width * right2[0];
9782 vert[10] = org2[1] + width * right2[1];
9783 vert[11] = org2[2] + width * right2[2];
9786 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)
9788 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
9789 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
9790 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
9791 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
9792 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
9793 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
9794 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
9795 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
9796 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
9797 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
9798 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
9799 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
9802 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
9807 VectorSet(v, x, y, z);
9808 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
9809 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
9811 if (i == mesh->numvertices)
9813 if (mesh->numvertices < mesh->maxvertices)
9815 VectorCopy(v, vertex3f);
9816 mesh->numvertices++;
9818 return mesh->numvertices;
9824 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
9828 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9829 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9830 e = mesh->element3i + mesh->numtriangles * 3;
9831 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
9833 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
9834 if (mesh->numtriangles < mesh->maxtriangles)
9839 mesh->numtriangles++;
9841 element[1] = element[2];
9845 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
9849 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9850 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9851 e = mesh->element3i + mesh->numtriangles * 3;
9852 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
9854 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
9855 if (mesh->numtriangles < mesh->maxtriangles)
9860 mesh->numtriangles++;
9862 element[1] = element[2];
9866 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
9867 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
9869 int planenum, planenum2;
9872 mplane_t *plane, *plane2;
9874 double temppoints[2][256*3];
9875 // figure out how large a bounding box we need to properly compute this brush
9877 for (w = 0;w < numplanes;w++)
9878 maxdist = max(maxdist, fabs(planes[w].dist));
9879 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
9880 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
9881 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
9885 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
9886 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
9888 if (planenum2 == planenum)
9890 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);
9893 if (tempnumpoints < 3)
9895 // generate elements forming a triangle fan for this polygon
9896 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
9900 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)
9902 texturelayer_t *layer;
9903 layer = t->currentlayers + t->currentnumlayers++;
9905 layer->depthmask = depthmask;
9906 layer->blendfunc1 = blendfunc1;
9907 layer->blendfunc2 = blendfunc2;
9908 layer->texture = texture;
9909 layer->texmatrix = *matrix;
9910 layer->color[0] = r;
9911 layer->color[1] = g;
9912 layer->color[2] = b;
9913 layer->color[3] = a;
9916 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
9918 if(parms[0] == 0 && parms[1] == 0)
9920 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
9921 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
9926 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
9929 index = parms[2] + r_refdef.scene.time * parms[3];
9930 index -= floor(index);
9931 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
9934 case Q3WAVEFUNC_NONE:
9935 case Q3WAVEFUNC_NOISE:
9936 case Q3WAVEFUNC_COUNT:
9939 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
9940 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
9941 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
9942 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
9943 case Q3WAVEFUNC_TRIANGLE:
9945 f = index - floor(index);
9956 f = parms[0] + parms[1] * f;
9957 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
9958 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
9962 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
9967 matrix4x4_t matrix, temp;
9968 switch(tcmod->tcmod)
9972 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9973 matrix = r_waterscrollmatrix;
9975 matrix = identitymatrix;
9977 case Q3TCMOD_ENTITYTRANSLATE:
9978 // this is used in Q3 to allow the gamecode to control texcoord
9979 // scrolling on the entity, which is not supported in darkplaces yet.
9980 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
9982 case Q3TCMOD_ROTATE:
9983 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
9984 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
9985 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
9988 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
9990 case Q3TCMOD_SCROLL:
9991 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
9993 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
9994 w = (int) tcmod->parms[0];
9995 h = (int) tcmod->parms[1];
9996 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
9998 idx = (int) floor(f * w * h);
9999 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10001 case Q3TCMOD_STRETCH:
10002 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10003 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10005 case Q3TCMOD_TRANSFORM:
10006 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
10007 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
10008 VectorSet(tcmat + 6, 0 , 0 , 1);
10009 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
10010 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10012 case Q3TCMOD_TURBULENT:
10013 // this is handled in the RSurf_PrepareVertices function
10014 matrix = identitymatrix;
10018 Matrix4x4_Concat(texmatrix, &matrix, &temp);
10021 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10023 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10024 char name[MAX_QPATH];
10025 skinframe_t *skinframe;
10026 unsigned char pixels[296*194];
10027 strlcpy(cache->name, skinname, sizeof(cache->name));
10028 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10029 if (developer_loading.integer)
10030 Con_Printf("loading %s\n", name);
10031 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10032 if (!skinframe || !skinframe->base)
10035 fs_offset_t filesize;
10037 f = FS_LoadFile(name, tempmempool, true, &filesize);
10040 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10041 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10045 cache->skinframe = skinframe;
10048 texture_t *R_GetCurrentTexture(texture_t *t)
10051 const entity_render_t *ent = rsurface.entity;
10052 dp_model_t *model = ent->model;
10053 q3shaderinfo_layer_tcmod_t *tcmod;
10055 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10056 return t->currentframe;
10057 t->update_lastrenderframe = r_textureframe;
10058 t->update_lastrenderentity = (void *)ent;
10060 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10061 t->camera_entity = ent->entitynumber;
10063 t->camera_entity = 0;
10065 // switch to an alternate material if this is a q1bsp animated material
10067 texture_t *texture = t;
10068 int s = rsurface.ent_skinnum;
10069 if ((unsigned int)s >= (unsigned int)model->numskins)
10071 if (model->skinscenes)
10073 if (model->skinscenes[s].framecount > 1)
10074 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10076 s = model->skinscenes[s].firstframe;
10079 t = t + s * model->num_surfaces;
10082 // use an alternate animation if the entity's frame is not 0,
10083 // and only if the texture has an alternate animation
10084 if (rsurface.ent_alttextures && t->anim_total[1])
10085 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10087 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10089 texture->currentframe = t;
10092 // update currentskinframe to be a qw skin or animation frame
10093 if (rsurface.ent_qwskin >= 0)
10095 i = rsurface.ent_qwskin;
10096 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10098 r_qwskincache_size = cl.maxclients;
10100 Mem_Free(r_qwskincache);
10101 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10103 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10104 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10105 t->currentskinframe = r_qwskincache[i].skinframe;
10106 if (t->currentskinframe == NULL)
10107 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10109 else if (t->numskinframes >= 2)
10110 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10111 if (t->backgroundnumskinframes >= 2)
10112 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10114 t->currentmaterialflags = t->basematerialflags;
10115 t->currentalpha = rsurface.colormod[3];
10116 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10117 t->currentalpha *= r_wateralpha.value;
10118 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10119 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10120 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10121 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10122 if (!(rsurface.ent_flags & RENDER_LIGHT))
10123 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10124 else if (FAKELIGHT_ENABLED)
10126 // no modellight if using fakelight for the map
10128 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10130 // pick a model lighting mode
10131 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10132 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10134 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10136 if (rsurface.ent_flags & RENDER_ADDITIVE)
10137 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10138 else if (t->currentalpha < 1)
10139 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10140 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10141 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10142 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10143 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10144 if (t->backgroundnumskinframes)
10145 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10146 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10148 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10149 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10152 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10153 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10154 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10156 // there is no tcmod
10157 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10159 t->currenttexmatrix = r_waterscrollmatrix;
10160 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10162 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10164 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10165 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10168 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10169 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10170 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10171 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10173 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10174 if (t->currentskinframe->qpixels)
10175 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10176 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10177 if (!t->basetexture)
10178 t->basetexture = r_texture_notexture;
10179 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10180 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10181 t->nmaptexture = t->currentskinframe->nmap;
10182 if (!t->nmaptexture)
10183 t->nmaptexture = r_texture_blanknormalmap;
10184 t->glosstexture = r_texture_black;
10185 t->glowtexture = t->currentskinframe->glow;
10186 t->fogtexture = t->currentskinframe->fog;
10187 t->reflectmasktexture = t->currentskinframe->reflect;
10188 if (t->backgroundnumskinframes)
10190 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10191 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10192 t->backgroundglosstexture = r_texture_black;
10193 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10194 if (!t->backgroundnmaptexture)
10195 t->backgroundnmaptexture = r_texture_blanknormalmap;
10199 t->backgroundbasetexture = r_texture_white;
10200 t->backgroundnmaptexture = r_texture_blanknormalmap;
10201 t->backgroundglosstexture = r_texture_black;
10202 t->backgroundglowtexture = NULL;
10204 t->specularpower = r_shadow_glossexponent.value;
10205 // TODO: store reference values for these in the texture?
10206 t->specularscale = 0;
10207 if (r_shadow_gloss.integer > 0)
10209 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10211 if (r_shadow_glossintensity.value > 0)
10213 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10214 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10215 t->specularscale = r_shadow_glossintensity.value;
10218 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10220 t->glosstexture = r_texture_white;
10221 t->backgroundglosstexture = r_texture_white;
10222 t->specularscale = r_shadow_gloss2intensity.value;
10223 t->specularpower = r_shadow_gloss2exponent.value;
10226 t->specularscale *= t->specularscalemod;
10227 t->specularpower *= t->specularpowermod;
10229 // lightmaps mode looks bad with dlights using actual texturing, so turn
10230 // off the colormap and glossmap, but leave the normalmap on as it still
10231 // accurately represents the shading involved
10232 if (gl_lightmaps.integer)
10234 t->basetexture = r_texture_grey128;
10235 t->pantstexture = r_texture_black;
10236 t->shirttexture = r_texture_black;
10237 t->nmaptexture = r_texture_blanknormalmap;
10238 t->glosstexture = r_texture_black;
10239 t->glowtexture = NULL;
10240 t->fogtexture = NULL;
10241 t->reflectmasktexture = NULL;
10242 t->backgroundbasetexture = NULL;
10243 t->backgroundnmaptexture = r_texture_blanknormalmap;
10244 t->backgroundglosstexture = r_texture_black;
10245 t->backgroundglowtexture = NULL;
10246 t->specularscale = 0;
10247 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10250 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10251 VectorClear(t->dlightcolor);
10252 t->currentnumlayers = 0;
10253 if (t->currentmaterialflags & MATERIALFLAG_WALL)
10255 int blendfunc1, blendfunc2;
10256 qboolean depthmask;
10257 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10259 blendfunc1 = GL_SRC_ALPHA;
10260 blendfunc2 = GL_ONE;
10262 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10264 blendfunc1 = GL_SRC_ALPHA;
10265 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10267 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10269 blendfunc1 = t->customblendfunc[0];
10270 blendfunc2 = t->customblendfunc[1];
10274 blendfunc1 = GL_ONE;
10275 blendfunc2 = GL_ZERO;
10277 // don't colormod evilblend textures
10278 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10279 VectorSet(t->lightmapcolor, 1, 1, 1);
10280 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10281 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10283 // fullbright is not affected by r_refdef.lightmapintensity
10284 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]);
10285 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10286 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]);
10287 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10288 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]);
10292 vec3_t ambientcolor;
10294 // set the color tint used for lights affecting this surface
10295 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10297 // q3bsp has no lightmap updates, so the lightstylevalue that
10298 // would normally be baked into the lightmap must be
10299 // applied to the color
10300 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10301 if (model->type == mod_brushq3)
10302 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10303 colorscale *= r_refdef.lightmapintensity;
10304 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10305 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10306 // basic lit geometry
10307 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]);
10308 // add pants/shirt if needed
10309 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10310 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]);
10311 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10312 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]);
10313 // now add ambient passes if needed
10314 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10316 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]);
10317 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10318 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]);
10319 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10320 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]);
10323 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10324 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]);
10325 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10327 // if this is opaque use alpha blend which will darken the earlier
10330 // if this is an alpha blended material, all the earlier passes
10331 // were darkened by fog already, so we only need to add the fog
10332 // color ontop through the fog mask texture
10334 // if this is an additive blended material, all the earlier passes
10335 // were darkened by fog already, and we should not add fog color
10336 // (because the background was not darkened, there is no fog color
10337 // that was lost behind it).
10338 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]);
10342 return t->currentframe;
10345 rsurfacestate_t rsurface;
10347 void RSurf_ActiveWorldEntity(void)
10349 dp_model_t *model = r_refdef.scene.worldmodel;
10350 //if (rsurface.entity == r_refdef.scene.worldentity)
10352 rsurface.entity = r_refdef.scene.worldentity;
10353 rsurface.skeleton = NULL;
10354 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10355 rsurface.ent_skinnum = 0;
10356 rsurface.ent_qwskin = -1;
10357 rsurface.ent_shadertime = 0;
10358 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10359 rsurface.matrix = identitymatrix;
10360 rsurface.inversematrix = identitymatrix;
10361 rsurface.matrixscale = 1;
10362 rsurface.inversematrixscale = 1;
10363 R_EntityMatrix(&identitymatrix);
10364 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10365 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10366 rsurface.fograngerecip = r_refdef.fograngerecip;
10367 rsurface.fogheightfade = r_refdef.fogheightfade;
10368 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10369 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10370 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10371 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10372 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10373 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10374 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10375 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10376 rsurface.colormod[3] = 1;
10377 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);
10378 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10379 rsurface.frameblend[0].lerp = 1;
10380 rsurface.ent_alttextures = false;
10381 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10382 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10383 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
10384 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10385 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10386 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10387 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10388 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10389 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10390 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10391 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10392 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
10393 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10394 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10395 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
10396 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10397 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10398 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
10399 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10400 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10401 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
10402 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10403 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10404 rsurface.modelelement3i = model->surfmesh.data_element3i;
10405 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10406 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10407 rsurface.modelelement3s = model->surfmesh.data_element3s;
10408 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10409 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10410 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10411 rsurface.modelnumvertices = model->surfmesh.num_vertices;
10412 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10413 rsurface.modelsurfaces = model->data_surfaces;
10414 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10415 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10416 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
10417 rsurface.modelgeneratedvertex = false;
10418 rsurface.batchgeneratedvertex = false;
10419 rsurface.batchfirstvertex = 0;
10420 rsurface.batchnumvertices = 0;
10421 rsurface.batchfirsttriangle = 0;
10422 rsurface.batchnumtriangles = 0;
10423 rsurface.batchvertex3f = NULL;
10424 rsurface.batchvertex3f_vertexbuffer = NULL;
10425 rsurface.batchvertex3f_bufferoffset = 0;
10426 rsurface.batchsvector3f = NULL;
10427 rsurface.batchsvector3f_vertexbuffer = NULL;
10428 rsurface.batchsvector3f_bufferoffset = 0;
10429 rsurface.batchtvector3f = NULL;
10430 rsurface.batchtvector3f_vertexbuffer = NULL;
10431 rsurface.batchtvector3f_bufferoffset = 0;
10432 rsurface.batchnormal3f = NULL;
10433 rsurface.batchnormal3f_vertexbuffer = NULL;
10434 rsurface.batchnormal3f_bufferoffset = 0;
10435 rsurface.batchlightmapcolor4f = NULL;
10436 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10437 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10438 rsurface.batchtexcoordtexture2f = NULL;
10439 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10440 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10441 rsurface.batchtexcoordlightmap2f = NULL;
10442 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10443 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10444 rsurface.batchvertexmesh = NULL;
10445 rsurface.batchvertexmeshbuffer = NULL;
10446 rsurface.batchvertex3fbuffer = NULL;
10447 rsurface.batchelement3i = NULL;
10448 rsurface.batchelement3i_indexbuffer = NULL;
10449 rsurface.batchelement3i_bufferoffset = 0;
10450 rsurface.batchelement3s = NULL;
10451 rsurface.batchelement3s_indexbuffer = NULL;
10452 rsurface.batchelement3s_bufferoffset = 0;
10453 rsurface.passcolor4f = NULL;
10454 rsurface.passcolor4f_vertexbuffer = NULL;
10455 rsurface.passcolor4f_bufferoffset = 0;
10458 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10460 dp_model_t *model = ent->model;
10461 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10463 rsurface.entity = (entity_render_t *)ent;
10464 rsurface.skeleton = ent->skeleton;
10465 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10466 rsurface.ent_skinnum = ent->skinnum;
10467 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;
10468 rsurface.ent_shadertime = ent->shadertime;
10469 rsurface.ent_flags = ent->flags;
10470 rsurface.matrix = ent->matrix;
10471 rsurface.inversematrix = ent->inversematrix;
10472 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10473 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10474 R_EntityMatrix(&rsurface.matrix);
10475 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10476 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10477 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10478 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10479 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10480 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10481 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10482 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10483 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10484 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10485 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10486 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10487 rsurface.colormod[3] = ent->alpha;
10488 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10489 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10490 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10491 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10492 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10493 if (ent->model->brush.submodel && !prepass)
10495 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10496 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10498 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10500 if (ent->animcache_vertex3f)
10502 rsurface.modelvertex3f = ent->animcache_vertex3f;
10503 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10504 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10505 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10506 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
10507 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
10508 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
10510 else if (wanttangents)
10512 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10513 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10514 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10515 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10516 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
10517 rsurface.modelvertexmesh = NULL;
10518 rsurface.modelvertexmeshbuffer = NULL;
10519 rsurface.modelvertex3fbuffer = NULL;
10521 else if (wantnormals)
10523 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10524 rsurface.modelsvector3f = NULL;
10525 rsurface.modeltvector3f = NULL;
10526 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10527 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
10528 rsurface.modelvertexmesh = NULL;
10529 rsurface.modelvertexmeshbuffer = NULL;
10530 rsurface.modelvertex3fbuffer = NULL;
10534 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10535 rsurface.modelsvector3f = NULL;
10536 rsurface.modeltvector3f = NULL;
10537 rsurface.modelnormal3f = NULL;
10538 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
10539 rsurface.modelvertexmesh = NULL;
10540 rsurface.modelvertexmeshbuffer = NULL;
10541 rsurface.modelvertex3fbuffer = NULL;
10543 rsurface.modelvertex3f_vertexbuffer = 0;
10544 rsurface.modelvertex3f_bufferoffset = 0;
10545 rsurface.modelsvector3f_vertexbuffer = 0;
10546 rsurface.modelsvector3f_bufferoffset = 0;
10547 rsurface.modeltvector3f_vertexbuffer = 0;
10548 rsurface.modeltvector3f_bufferoffset = 0;
10549 rsurface.modelnormal3f_vertexbuffer = 0;
10550 rsurface.modelnormal3f_bufferoffset = 0;
10551 rsurface.modelgeneratedvertex = true;
10555 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
10556 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10557 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10558 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10559 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10560 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10561 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10562 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10563 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10564 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
10565 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10566 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10567 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10568 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10569 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
10570 rsurface.modelgeneratedvertex = false;
10572 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
10573 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10574 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10575 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
10576 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10577 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10578 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
10579 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10580 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10581 rsurface.modelelement3i = model->surfmesh.data_element3i;
10582 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10583 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10584 rsurface.modelelement3s = model->surfmesh.data_element3s;
10585 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10586 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10587 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10588 rsurface.modelnumvertices = model->surfmesh.num_vertices;
10589 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10590 rsurface.modelsurfaces = model->data_surfaces;
10591 rsurface.batchgeneratedvertex = false;
10592 rsurface.batchfirstvertex = 0;
10593 rsurface.batchnumvertices = 0;
10594 rsurface.batchfirsttriangle = 0;
10595 rsurface.batchnumtriangles = 0;
10596 rsurface.batchvertex3f = NULL;
10597 rsurface.batchvertex3f_vertexbuffer = NULL;
10598 rsurface.batchvertex3f_bufferoffset = 0;
10599 rsurface.batchsvector3f = NULL;
10600 rsurface.batchsvector3f_vertexbuffer = NULL;
10601 rsurface.batchsvector3f_bufferoffset = 0;
10602 rsurface.batchtvector3f = NULL;
10603 rsurface.batchtvector3f_vertexbuffer = NULL;
10604 rsurface.batchtvector3f_bufferoffset = 0;
10605 rsurface.batchnormal3f = NULL;
10606 rsurface.batchnormal3f_vertexbuffer = NULL;
10607 rsurface.batchnormal3f_bufferoffset = 0;
10608 rsurface.batchlightmapcolor4f = NULL;
10609 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10610 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10611 rsurface.batchtexcoordtexture2f = NULL;
10612 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10613 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10614 rsurface.batchtexcoordlightmap2f = NULL;
10615 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10616 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10617 rsurface.batchvertexmesh = NULL;
10618 rsurface.batchvertexmeshbuffer = NULL;
10619 rsurface.batchvertex3fbuffer = NULL;
10620 rsurface.batchelement3i = NULL;
10621 rsurface.batchelement3i_indexbuffer = NULL;
10622 rsurface.batchelement3i_bufferoffset = 0;
10623 rsurface.batchelement3s = NULL;
10624 rsurface.batchelement3s_indexbuffer = NULL;
10625 rsurface.batchelement3s_bufferoffset = 0;
10626 rsurface.passcolor4f = NULL;
10627 rsurface.passcolor4f_vertexbuffer = NULL;
10628 rsurface.passcolor4f_bufferoffset = 0;
10631 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)
10633 rsurface.entity = r_refdef.scene.worldentity;
10634 rsurface.skeleton = NULL;
10635 rsurface.ent_skinnum = 0;
10636 rsurface.ent_qwskin = -1;
10637 rsurface.ent_shadertime = shadertime;
10638 rsurface.ent_flags = entflags;
10639 rsurface.modelnumvertices = numvertices;
10640 rsurface.modelnumtriangles = numtriangles;
10641 rsurface.matrix = *matrix;
10642 rsurface.inversematrix = *inversematrix;
10643 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10644 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10645 R_EntityMatrix(&rsurface.matrix);
10646 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10647 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10648 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10649 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10650 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10651 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10652 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10653 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10654 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10655 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10656 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10657 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
10658 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);
10659 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10660 rsurface.frameblend[0].lerp = 1;
10661 rsurface.ent_alttextures = false;
10662 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10663 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10666 rsurface.modelvertex3f = (float *)vertex3f;
10667 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10668 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10669 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10671 else if (wantnormals)
10673 rsurface.modelvertex3f = (float *)vertex3f;
10674 rsurface.modelsvector3f = NULL;
10675 rsurface.modeltvector3f = NULL;
10676 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10680 rsurface.modelvertex3f = (float *)vertex3f;
10681 rsurface.modelsvector3f = NULL;
10682 rsurface.modeltvector3f = NULL;
10683 rsurface.modelnormal3f = NULL;
10685 rsurface.modelvertexmesh = NULL;
10686 rsurface.modelvertexmeshbuffer = NULL;
10687 rsurface.modelvertex3fbuffer = NULL;
10688 rsurface.modelvertex3f_vertexbuffer = 0;
10689 rsurface.modelvertex3f_bufferoffset = 0;
10690 rsurface.modelsvector3f_vertexbuffer = 0;
10691 rsurface.modelsvector3f_bufferoffset = 0;
10692 rsurface.modeltvector3f_vertexbuffer = 0;
10693 rsurface.modeltvector3f_bufferoffset = 0;
10694 rsurface.modelnormal3f_vertexbuffer = 0;
10695 rsurface.modelnormal3f_bufferoffset = 0;
10696 rsurface.modelgeneratedvertex = true;
10697 rsurface.modellightmapcolor4f = (float *)color4f;
10698 rsurface.modellightmapcolor4f_vertexbuffer = 0;
10699 rsurface.modellightmapcolor4f_bufferoffset = 0;
10700 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
10701 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
10702 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
10703 rsurface.modeltexcoordlightmap2f = NULL;
10704 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
10705 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
10706 rsurface.modelelement3i = (int *)element3i;
10707 rsurface.modelelement3i_indexbuffer = NULL;
10708 rsurface.modelelement3i_bufferoffset = 0;
10709 rsurface.modelelement3s = (unsigned short *)element3s;
10710 rsurface.modelelement3s_indexbuffer = NULL;
10711 rsurface.modelelement3s_bufferoffset = 0;
10712 rsurface.modellightmapoffsets = NULL;
10713 rsurface.modelsurfaces = NULL;
10714 rsurface.batchgeneratedvertex = false;
10715 rsurface.batchfirstvertex = 0;
10716 rsurface.batchnumvertices = 0;
10717 rsurface.batchfirsttriangle = 0;
10718 rsurface.batchnumtriangles = 0;
10719 rsurface.batchvertex3f = NULL;
10720 rsurface.batchvertex3f_vertexbuffer = NULL;
10721 rsurface.batchvertex3f_bufferoffset = 0;
10722 rsurface.batchsvector3f = NULL;
10723 rsurface.batchsvector3f_vertexbuffer = NULL;
10724 rsurface.batchsvector3f_bufferoffset = 0;
10725 rsurface.batchtvector3f = NULL;
10726 rsurface.batchtvector3f_vertexbuffer = NULL;
10727 rsurface.batchtvector3f_bufferoffset = 0;
10728 rsurface.batchnormal3f = NULL;
10729 rsurface.batchnormal3f_vertexbuffer = NULL;
10730 rsurface.batchnormal3f_bufferoffset = 0;
10731 rsurface.batchlightmapcolor4f = NULL;
10732 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10733 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10734 rsurface.batchtexcoordtexture2f = NULL;
10735 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10736 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10737 rsurface.batchtexcoordlightmap2f = NULL;
10738 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10739 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10740 rsurface.batchvertexmesh = NULL;
10741 rsurface.batchvertexmeshbuffer = NULL;
10742 rsurface.batchvertex3fbuffer = NULL;
10743 rsurface.batchelement3i = NULL;
10744 rsurface.batchelement3i_indexbuffer = NULL;
10745 rsurface.batchelement3i_bufferoffset = 0;
10746 rsurface.batchelement3s = NULL;
10747 rsurface.batchelement3s_indexbuffer = NULL;
10748 rsurface.batchelement3s_bufferoffset = 0;
10749 rsurface.passcolor4f = NULL;
10750 rsurface.passcolor4f_vertexbuffer = NULL;
10751 rsurface.passcolor4f_bufferoffset = 0;
10753 if (rsurface.modelnumvertices && rsurface.modelelement3i)
10755 if ((wantnormals || wanttangents) && !normal3f)
10757 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10758 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
10760 if (wanttangents && !svector3f)
10762 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10763 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10764 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
10769 float RSurf_FogPoint(const float *v)
10771 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10772 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
10773 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
10774 float FogHeightFade = r_refdef.fogheightfade;
10776 unsigned int fogmasktableindex;
10777 if (r_refdef.fogplaneviewabove)
10778 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10780 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10781 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
10782 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10785 float RSurf_FogVertex(const float *v)
10787 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10788 float FogPlaneViewDist = rsurface.fogplaneviewdist;
10789 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
10790 float FogHeightFade = rsurface.fogheightfade;
10792 unsigned int fogmasktableindex;
10793 if (r_refdef.fogplaneviewabove)
10794 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10796 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10797 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
10798 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10801 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
10804 for (i = 0;i < numelements;i++)
10805 outelement3i[i] = inelement3i[i] + adjust;
10808 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
10809 extern cvar_t gl_vbo;
10810 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
10818 int surfacefirsttriangle;
10819 int surfacenumtriangles;
10820 int surfacefirstvertex;
10821 int surfaceendvertex;
10822 int surfacenumvertices;
10823 int batchnumvertices;
10824 int batchnumtriangles;
10828 qboolean dynamicvertex;
10832 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
10833 float waveparms[4];
10834 q3shaderinfo_deform_t *deform;
10835 const msurface_t *surface, *firstsurface;
10836 r_vertexmesh_t *vertexmesh;
10837 if (!texturenumsurfaces)
10839 // find vertex range of this surface batch
10841 firstsurface = texturesurfacelist[0];
10842 firsttriangle = firstsurface->num_firsttriangle;
10843 batchnumvertices = 0;
10844 batchnumtriangles = 0;
10845 firstvertex = endvertex = firstsurface->num_firstvertex;
10846 for (i = 0;i < texturenumsurfaces;i++)
10848 surface = texturesurfacelist[i];
10849 if (surface != firstsurface + i)
10851 surfacefirstvertex = surface->num_firstvertex;
10852 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
10853 surfacenumvertices = surface->num_vertices;
10854 surfacenumtriangles = surface->num_triangles;
10855 if (firstvertex > surfacefirstvertex)
10856 firstvertex = surfacefirstvertex;
10857 if (endvertex < surfaceendvertex)
10858 endvertex = surfaceendvertex;
10859 batchnumvertices += surfacenumvertices;
10860 batchnumtriangles += surfacenumtriangles;
10863 // we now know the vertex range used, and if there are any gaps in it
10864 rsurface.batchfirstvertex = firstvertex;
10865 rsurface.batchnumvertices = endvertex - firstvertex;
10866 rsurface.batchfirsttriangle = firsttriangle;
10867 rsurface.batchnumtriangles = batchnumtriangles;
10869 // this variable holds flags for which properties have been updated that
10870 // may require regenerating vertexmesh array...
10873 // check if any dynamic vertex processing must occur
10874 dynamicvertex = false;
10876 // if there is a chance of animated vertex colors, it's a dynamic batch
10877 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
10879 dynamicvertex = true;
10880 batchneed |= BATCHNEED_NOGAPS;
10881 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
10884 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
10886 switch (deform->deform)
10889 case Q3DEFORM_PROJECTIONSHADOW:
10890 case Q3DEFORM_TEXT0:
10891 case Q3DEFORM_TEXT1:
10892 case Q3DEFORM_TEXT2:
10893 case Q3DEFORM_TEXT3:
10894 case Q3DEFORM_TEXT4:
10895 case Q3DEFORM_TEXT5:
10896 case Q3DEFORM_TEXT6:
10897 case Q3DEFORM_TEXT7:
10898 case Q3DEFORM_NONE:
10900 case Q3DEFORM_AUTOSPRITE:
10901 dynamicvertex = true;
10902 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10903 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10905 case Q3DEFORM_AUTOSPRITE2:
10906 dynamicvertex = true;
10907 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10908 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10910 case Q3DEFORM_NORMAL:
10911 dynamicvertex = true;
10912 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10913 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10915 case Q3DEFORM_WAVE:
10916 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10917 break; // if wavefunc is a nop, ignore this transform
10918 dynamicvertex = true;
10919 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10920 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10922 case Q3DEFORM_BULGE:
10923 dynamicvertex = true;
10924 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10925 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10927 case Q3DEFORM_MOVE:
10928 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10929 break; // if wavefunc is a nop, ignore this transform
10930 dynamicvertex = true;
10931 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
10932 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
10936 switch(rsurface.texture->tcgen.tcgen)
10939 case Q3TCGEN_TEXTURE:
10941 case Q3TCGEN_LIGHTMAP:
10942 dynamicvertex = true;
10943 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
10944 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
10946 case Q3TCGEN_VECTOR:
10947 dynamicvertex = true;
10948 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
10949 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
10951 case Q3TCGEN_ENVIRONMENT:
10952 dynamicvertex = true;
10953 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
10954 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
10957 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10959 dynamicvertex = true;
10960 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10961 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
10964 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
10966 dynamicvertex = true;
10967 batchneed |= BATCHNEED_NOGAPS;
10968 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
10971 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
10973 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
10974 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
10975 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
10976 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
10977 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
10978 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
10979 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
10982 // when the model data has no vertex buffer (dynamic mesh), we need to
10984 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
10985 batchneed |= BATCHNEED_NOGAPS;
10987 // if needsupdate, we have to do a dynamic vertex batch for sure
10988 if (needsupdate & batchneed)
10989 dynamicvertex = true;
10991 // see if we need to build vertexmesh from arrays
10992 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
10993 dynamicvertex = true;
10995 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
10996 // also some drivers strongly dislike firstvertex
10997 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
10998 dynamicvertex = true;
11000 rsurface.batchvertex3f = rsurface.modelvertex3f;
11001 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11002 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11003 rsurface.batchsvector3f = rsurface.modelsvector3f;
11004 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11005 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11006 rsurface.batchtvector3f = rsurface.modeltvector3f;
11007 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11008 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11009 rsurface.batchnormal3f = rsurface.modelnormal3f;
11010 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11011 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11012 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11013 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
11014 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11015 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11016 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
11017 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
11018 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11019 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11020 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11021 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
11022 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11023 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11024 rsurface.batchelement3i = rsurface.modelelement3i;
11025 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11026 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11027 rsurface.batchelement3s = rsurface.modelelement3s;
11028 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11029 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11031 // if any dynamic vertex processing has to occur in software, we copy the
11032 // entire surface list together before processing to rebase the vertices
11033 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11035 // if any gaps exist and we do not have a static vertex buffer, we have to
11036 // copy the surface list together to avoid wasting upload bandwidth on the
11037 // vertices in the gaps.
11039 // if gaps exist and we have a static vertex buffer, we still have to
11040 // combine the index buffer ranges into one dynamic index buffer.
11042 // in all cases we end up with data that can be drawn in one call.
11044 if (!dynamicvertex)
11046 // static vertex data, just set pointers...
11047 rsurface.batchgeneratedvertex = false;
11048 // if there are gaps, we want to build a combined index buffer,
11049 // otherwise use the original static buffer with an appropriate offset
11052 // build a new triangle elements array for this batch
11053 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11054 rsurface.batchfirsttriangle = 0;
11056 for (i = 0;i < texturenumsurfaces;i++)
11058 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11059 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11060 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11061 numtriangles += surfacenumtriangles;
11063 rsurface.batchelement3i_indexbuffer = NULL;
11064 rsurface.batchelement3i_bufferoffset = 0;
11065 rsurface.batchelement3s = NULL;
11066 rsurface.batchelement3s_indexbuffer = NULL;
11067 rsurface.batchelement3s_bufferoffset = 0;
11068 if (endvertex <= 65536)
11070 // make a 16bit (unsigned short) index array if possible
11071 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11072 for (i = 0;i < numtriangles*3;i++)
11073 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11079 // something needs software processing, do it for real...
11080 // we only directly handle separate array data in this case and then
11081 // generate interleaved data if needed...
11082 rsurface.batchgeneratedvertex = true;
11084 // now copy the vertex data into a combined array and make an index array
11085 // (this is what Quake3 does all the time)
11086 //if (gaps || rsurface.batchfirstvertex)
11088 rsurface.batchvertex3fbuffer = NULL;
11089 rsurface.batchvertexmesh = NULL;
11090 rsurface.batchvertexmeshbuffer = NULL;
11091 rsurface.batchvertex3f = NULL;
11092 rsurface.batchvertex3f_vertexbuffer = NULL;
11093 rsurface.batchvertex3f_bufferoffset = 0;
11094 rsurface.batchsvector3f = NULL;
11095 rsurface.batchsvector3f_vertexbuffer = NULL;
11096 rsurface.batchsvector3f_bufferoffset = 0;
11097 rsurface.batchtvector3f = NULL;
11098 rsurface.batchtvector3f_vertexbuffer = NULL;
11099 rsurface.batchtvector3f_bufferoffset = 0;
11100 rsurface.batchnormal3f = NULL;
11101 rsurface.batchnormal3f_vertexbuffer = NULL;
11102 rsurface.batchnormal3f_bufferoffset = 0;
11103 rsurface.batchlightmapcolor4f = NULL;
11104 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11105 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11106 rsurface.batchtexcoordtexture2f = NULL;
11107 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11108 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11109 rsurface.batchtexcoordlightmap2f = NULL;
11110 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11111 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11112 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11113 rsurface.batchelement3i_indexbuffer = NULL;
11114 rsurface.batchelement3i_bufferoffset = 0;
11115 rsurface.batchelement3s = NULL;
11116 rsurface.batchelement3s_indexbuffer = NULL;
11117 rsurface.batchelement3s_bufferoffset = 0;
11118 // we'll only be setting up certain arrays as needed
11119 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11120 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
11121 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11122 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11123 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11124 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11125 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11127 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11128 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11130 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11131 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11132 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11133 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11134 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11135 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11138 for (i = 0;i < texturenumsurfaces;i++)
11140 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11141 surfacenumvertices = texturesurfacelist[i]->num_vertices;
11142 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11143 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11144 // copy only the data requested
11145 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11146 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11147 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11149 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11150 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11151 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11152 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11153 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11155 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11156 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11158 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11159 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11160 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11161 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11162 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11163 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11165 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11166 numvertices += surfacenumvertices;
11167 numtriangles += surfacenumtriangles;
11170 // generate a 16bit index array as well if possible
11171 // (in general, dynamic batches fit)
11172 if (numvertices <= 65536)
11174 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11175 for (i = 0;i < numtriangles*3;i++)
11176 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11179 // since we've copied everything, the batch now starts at 0
11180 rsurface.batchfirstvertex = 0;
11181 rsurface.batchnumvertices = batchnumvertices;
11182 rsurface.batchfirsttriangle = 0;
11183 rsurface.batchnumtriangles = batchnumtriangles;
11186 // q1bsp surfaces rendered in vertex color mode have to have colors
11187 // calculated based on lightstyles
11188 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11190 // generate color arrays for the surfaces in this list
11194 const int *offsets;
11195 const unsigned char *lm;
11196 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11197 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11198 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11200 for (i = 0;i < texturenumsurfaces;i++)
11202 surface = texturesurfacelist[i];
11203 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11204 surfacenumvertices = surface->num_vertices;
11205 if (surface->lightmapinfo->samples)
11207 for (j = 0;j < surfacenumvertices;j++)
11209 lm = surface->lightmapinfo->samples + offsets[j];
11210 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11211 VectorScale(lm, scale, c);
11212 if (surface->lightmapinfo->styles[1] != 255)
11214 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11216 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11217 VectorMA(c, scale, lm, c);
11218 if (surface->lightmapinfo->styles[2] != 255)
11221 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11222 VectorMA(c, scale, lm, c);
11223 if (surface->lightmapinfo->styles[3] != 255)
11226 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11227 VectorMA(c, scale, lm, c);
11234 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);
11240 for (j = 0;j < surfacenumvertices;j++)
11242 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11249 // if vertices are deformed (sprite flares and things in maps, possibly
11250 // water waves, bulges and other deformations), modify the copied vertices
11252 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11254 switch (deform->deform)
11257 case Q3DEFORM_PROJECTIONSHADOW:
11258 case Q3DEFORM_TEXT0:
11259 case Q3DEFORM_TEXT1:
11260 case Q3DEFORM_TEXT2:
11261 case Q3DEFORM_TEXT3:
11262 case Q3DEFORM_TEXT4:
11263 case Q3DEFORM_TEXT5:
11264 case Q3DEFORM_TEXT6:
11265 case Q3DEFORM_TEXT7:
11266 case Q3DEFORM_NONE:
11268 case Q3DEFORM_AUTOSPRITE:
11269 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11270 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11271 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11272 VectorNormalize(newforward);
11273 VectorNormalize(newright);
11274 VectorNormalize(newup);
11275 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11276 // rsurface.batchvertex3f_vertexbuffer = NULL;
11277 // rsurface.batchvertex3f_bufferoffset = 0;
11278 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
11279 // rsurface.batchsvector3f_vertexbuffer = NULL;
11280 // rsurface.batchsvector3f_bufferoffset = 0;
11281 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
11282 // rsurface.batchtvector3f_vertexbuffer = NULL;
11283 // rsurface.batchtvector3f_bufferoffset = 0;
11284 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11285 // rsurface.batchnormal3f_vertexbuffer = NULL;
11286 // rsurface.batchnormal3f_bufferoffset = 0;
11287 // a single autosprite surface can contain multiple sprites...
11288 for (j = 0;j < batchnumvertices - 3;j += 4)
11290 VectorClear(center);
11291 for (i = 0;i < 4;i++)
11292 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11293 VectorScale(center, 0.25f, center);
11294 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11295 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11296 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11297 for (i = 0;i < 4;i++)
11299 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11300 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
11303 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11304 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11305 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);
11307 case Q3DEFORM_AUTOSPRITE2:
11308 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11309 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11310 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11311 VectorNormalize(newforward);
11312 VectorNormalize(newright);
11313 VectorNormalize(newup);
11314 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11315 // rsurface.batchvertex3f_vertexbuffer = NULL;
11316 // rsurface.batchvertex3f_bufferoffset = 0;
11318 const float *v1, *v2;
11328 memset(shortest, 0, sizeof(shortest));
11329 // a single autosprite surface can contain multiple sprites...
11330 for (j = 0;j < batchnumvertices - 3;j += 4)
11332 VectorClear(center);
11333 for (i = 0;i < 4;i++)
11334 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11335 VectorScale(center, 0.25f, center);
11336 // find the two shortest edges, then use them to define the
11337 // axis vectors for rotating around the central axis
11338 for (i = 0;i < 6;i++)
11340 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11341 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11342 l = VectorDistance2(v1, v2);
11343 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11344 if (v1[2] != v2[2])
11345 l += (1.0f / 1024.0f);
11346 if (shortest[0].length2 > l || i == 0)
11348 shortest[1] = shortest[0];
11349 shortest[0].length2 = l;
11350 shortest[0].v1 = v1;
11351 shortest[0].v2 = v2;
11353 else if (shortest[1].length2 > l || i == 1)
11355 shortest[1].length2 = l;
11356 shortest[1].v1 = v1;
11357 shortest[1].v2 = v2;
11360 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11361 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11362 // this calculates the right vector from the shortest edge
11363 // and the up vector from the edge midpoints
11364 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11365 VectorNormalize(right);
11366 VectorSubtract(end, start, up);
11367 VectorNormalize(up);
11368 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11369 VectorSubtract(rsurface.localvieworigin, center, forward);
11370 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11371 VectorNegate(forward, forward);
11372 VectorReflect(forward, 0, up, forward);
11373 VectorNormalize(forward);
11374 CrossProduct(up, forward, newright);
11375 VectorNormalize(newright);
11376 // rotate the quad around the up axis vector, this is made
11377 // especially easy by the fact we know the quad is flat,
11378 // so we only have to subtract the center position and
11379 // measure distance along the right vector, and then
11380 // multiply that by the newright vector and add back the
11382 // we also need to subtract the old position to undo the
11383 // displacement from the center, which we do with a
11384 // DotProduct, the subtraction/addition of center is also
11385 // optimized into DotProducts here
11386 l = DotProduct(right, center);
11387 for (i = 0;i < 4;i++)
11389 v1 = rsurface.batchvertex3f + 3*(j+i);
11390 f = DotProduct(right, v1) - l;
11391 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
11395 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11397 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11398 // rsurface.batchnormal3f_vertexbuffer = NULL;
11399 // rsurface.batchnormal3f_bufferoffset = 0;
11400 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11402 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11404 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11405 // rsurface.batchsvector3f_vertexbuffer = NULL;
11406 // rsurface.batchsvector3f_bufferoffset = 0;
11407 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11408 // rsurface.batchtvector3f_vertexbuffer = NULL;
11409 // rsurface.batchtvector3f_bufferoffset = 0;
11410 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);
11413 case Q3DEFORM_NORMAL:
11414 // deform the normals to make reflections wavey
11415 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11416 rsurface.batchnormal3f_vertexbuffer = NULL;
11417 rsurface.batchnormal3f_bufferoffset = 0;
11418 for (j = 0;j < batchnumvertices;j++)
11421 float *normal = rsurface.batchnormal3f + 3*j;
11422 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11423 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11424 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]);
11425 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]);
11426 VectorNormalize(normal);
11428 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11430 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11431 // rsurface.batchsvector3f_vertexbuffer = NULL;
11432 // rsurface.batchsvector3f_bufferoffset = 0;
11433 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11434 // rsurface.batchtvector3f_vertexbuffer = NULL;
11435 // rsurface.batchtvector3f_bufferoffset = 0;
11436 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);
11439 case Q3DEFORM_WAVE:
11440 // deform vertex array to make wavey water and flags and such
11441 waveparms[0] = deform->waveparms[0];
11442 waveparms[1] = deform->waveparms[1];
11443 waveparms[2] = deform->waveparms[2];
11444 waveparms[3] = deform->waveparms[3];
11445 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11446 break; // if wavefunc is a nop, don't make a dynamic vertex array
11447 // this is how a divisor of vertex influence on deformation
11448 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11449 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11450 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11451 // rsurface.batchvertex3f_vertexbuffer = NULL;
11452 // rsurface.batchvertex3f_bufferoffset = 0;
11453 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11454 // rsurface.batchnormal3f_vertexbuffer = NULL;
11455 // rsurface.batchnormal3f_bufferoffset = 0;
11456 for (j = 0;j < batchnumvertices;j++)
11458 // if the wavefunc depends on time, evaluate it per-vertex
11461 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11462 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11464 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
11466 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11467 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11468 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11470 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11471 // rsurface.batchsvector3f_vertexbuffer = NULL;
11472 // rsurface.batchsvector3f_bufferoffset = 0;
11473 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11474 // rsurface.batchtvector3f_vertexbuffer = NULL;
11475 // rsurface.batchtvector3f_bufferoffset = 0;
11476 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);
11479 case Q3DEFORM_BULGE:
11480 // deform vertex array to make the surface have moving bulges
11481 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11482 // rsurface.batchvertex3f_vertexbuffer = NULL;
11483 // rsurface.batchvertex3f_bufferoffset = 0;
11484 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11485 // rsurface.batchnormal3f_vertexbuffer = NULL;
11486 // rsurface.batchnormal3f_bufferoffset = 0;
11487 for (j = 0;j < batchnumvertices;j++)
11489 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
11490 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
11492 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11493 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11494 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11496 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11497 // rsurface.batchsvector3f_vertexbuffer = NULL;
11498 // rsurface.batchsvector3f_bufferoffset = 0;
11499 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11500 // rsurface.batchtvector3f_vertexbuffer = NULL;
11501 // rsurface.batchtvector3f_bufferoffset = 0;
11502 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);
11505 case Q3DEFORM_MOVE:
11506 // deform vertex array
11507 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11508 break; // if wavefunc is a nop, don't make a dynamic vertex array
11509 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
11510 VectorScale(deform->parms, scale, waveparms);
11511 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11512 // rsurface.batchvertex3f_vertexbuffer = NULL;
11513 // rsurface.batchvertex3f_bufferoffset = 0;
11514 for (j = 0;j < batchnumvertices;j++)
11515 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
11520 // generate texcoords based on the chosen texcoord source
11521 switch(rsurface.texture->tcgen.tcgen)
11524 case Q3TCGEN_TEXTURE:
11526 case Q3TCGEN_LIGHTMAP:
11527 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11528 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11529 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11530 if (rsurface.batchtexcoordlightmap2f)
11531 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
11533 case Q3TCGEN_VECTOR:
11534 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11535 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11536 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11537 for (j = 0;j < batchnumvertices;j++)
11539 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
11540 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
11543 case Q3TCGEN_ENVIRONMENT:
11544 // make environment reflections using a spheremap
11545 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11546 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11547 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11548 for (j = 0;j < batchnumvertices;j++)
11550 // identical to Q3A's method, but executed in worldspace so
11551 // carried models can be shiny too
11553 float viewer[3], d, reflected[3], worldreflected[3];
11555 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
11556 // VectorNormalize(viewer);
11558 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
11560 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
11561 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
11562 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
11563 // note: this is proportinal to viewer, so we can normalize later
11565 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
11566 VectorNormalize(worldreflected);
11568 // note: this sphere map only uses world x and z!
11569 // so positive and negative y will LOOK THE SAME.
11570 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
11571 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
11575 // the only tcmod that needs software vertex processing is turbulent, so
11576 // check for it here and apply the changes if needed
11577 // and we only support that as the first one
11578 // (handling a mixture of turbulent and other tcmods would be problematic
11579 // without punting it entirely to a software path)
11580 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11582 amplitude = rsurface.texture->tcmods[0].parms[1];
11583 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
11584 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11585 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11586 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11587 for (j = 0;j < batchnumvertices;j++)
11589 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);
11590 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
11594 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11596 // convert the modified arrays to vertex structs
11597 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
11598 // rsurface.batchvertexmeshbuffer = NULL;
11599 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
11600 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11601 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
11602 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
11603 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11604 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
11605 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
11607 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11609 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
11610 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
11613 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
11614 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11615 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
11616 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
11617 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11618 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
11619 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
11620 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11621 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
11625 void RSurf_DrawBatch(void)
11627 // sometimes a zero triangle surface (usually a degenerate patch) makes it
11628 // through the pipeline, killing it earlier in the pipeline would have
11629 // per-surface overhead rather than per-batch overhead, so it's best to
11630 // reject it here, before it hits glDraw.
11631 if (rsurface.batchnumtriangles == 0)
11634 // batch debugging code
11635 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
11641 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
11642 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
11645 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
11647 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
11649 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
11650 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);
11657 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);
11660 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
11662 // pick the closest matching water plane
11663 int planeindex, vertexindex, bestplaneindex = -1;
11667 r_waterstate_waterplane_t *p;
11668 qboolean prepared = false;
11670 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
11672 if(p->camera_entity != rsurface.texture->camera_entity)
11677 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11679 if(rsurface.batchnumvertices == 0)
11682 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
11684 Matrix4x4_Transform(&rsurface.matrix, v, vert);
11685 d += fabs(PlaneDiff(vert, &p->plane));
11687 if (bestd > d || bestplaneindex < 0)
11690 bestplaneindex = planeindex;
11693 return bestplaneindex;
11694 // NOTE: this MAY return a totally unrelated water plane; we can ignore
11695 // this situation though, as it might be better to render single larger
11696 // batches with useless stuff (backface culled for example) than to
11697 // render multiple smaller batches
11700 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
11703 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11704 rsurface.passcolor4f_vertexbuffer = 0;
11705 rsurface.passcolor4f_bufferoffset = 0;
11706 for (i = 0;i < rsurface.batchnumvertices;i++)
11707 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
11710 static void RSurf_DrawBatch_GL11_ApplyFog(void)
11717 if (rsurface.passcolor4f)
11719 // generate color arrays
11720 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11721 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11722 rsurface.passcolor4f_vertexbuffer = 0;
11723 rsurface.passcolor4f_bufferoffset = 0;
11724 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)
11726 f = RSurf_FogVertex(v);
11735 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11736 rsurface.passcolor4f_vertexbuffer = 0;
11737 rsurface.passcolor4f_bufferoffset = 0;
11738 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
11740 f = RSurf_FogVertex(v);
11749 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
11756 if (!rsurface.passcolor4f)
11758 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11759 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11760 rsurface.passcolor4f_vertexbuffer = 0;
11761 rsurface.passcolor4f_bufferoffset = 0;
11762 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)
11764 f = RSurf_FogVertex(v);
11765 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
11766 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
11767 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
11772 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
11777 if (!rsurface.passcolor4f)
11779 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11780 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11781 rsurface.passcolor4f_vertexbuffer = 0;
11782 rsurface.passcolor4f_bufferoffset = 0;
11783 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11792 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
11797 if (!rsurface.passcolor4f)
11799 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11800 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11801 rsurface.passcolor4f_vertexbuffer = 0;
11802 rsurface.passcolor4f_bufferoffset = 0;
11803 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11805 c2[0] = c[0] + r_refdef.scene.ambient;
11806 c2[1] = c[1] + r_refdef.scene.ambient;
11807 c2[2] = c[2] + r_refdef.scene.ambient;
11812 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11815 rsurface.passcolor4f = NULL;
11816 rsurface.passcolor4f_vertexbuffer = 0;
11817 rsurface.passcolor4f_bufferoffset = 0;
11818 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
11819 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11820 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11821 GL_Color(r, g, b, a);
11822 R_Mesh_TexBind(0, rsurface.lightmaptexture);
11826 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11828 // TODO: optimize applyfog && applycolor case
11829 // just apply fog if necessary, and tint the fog color array if necessary
11830 rsurface.passcolor4f = NULL;
11831 rsurface.passcolor4f_vertexbuffer = 0;
11832 rsurface.passcolor4f_bufferoffset = 0;
11833 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
11834 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11835 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11836 GL_Color(r, g, b, a);
11840 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11843 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11844 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11845 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11846 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
11847 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11848 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11849 GL_Color(r, g, b, a);
11853 static void RSurf_DrawBatch_GL11_ClampColor(void)
11858 if (!rsurface.passcolor4f)
11860 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
11862 c2[0] = bound(0.0f, c1[0], 1.0f);
11863 c2[1] = bound(0.0f, c1[1], 1.0f);
11864 c2[2] = bound(0.0f, c1[2], 1.0f);
11865 c2[3] = bound(0.0f, c1[3], 1.0f);
11869 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
11879 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11880 rsurface.passcolor4f_vertexbuffer = 0;
11881 rsurface.passcolor4f_bufferoffset = 0;
11882 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)
11884 f = -DotProduct(r_refdef.view.forward, n);
11886 f = f * 0.85 + 0.15; // work around so stuff won't get black
11887 f *= r_refdef.lightmapintensity;
11888 Vector4Set(c, f, f, f, 1);
11892 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11894 RSurf_DrawBatch_GL11_ApplyFakeLight();
11895 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
11896 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11897 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11898 GL_Color(r, g, b, a);
11902 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
11910 vec3_t ambientcolor;
11911 vec3_t diffusecolor;
11915 VectorCopy(rsurface.modellight_lightdir, lightdir);
11916 f = 0.5f * r_refdef.lightmapintensity;
11917 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
11918 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
11919 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
11920 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
11921 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
11922 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
11924 if (VectorLength2(diffusecolor) > 0)
11926 // q3-style directional shading
11927 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11928 rsurface.passcolor4f_vertexbuffer = 0;
11929 rsurface.passcolor4f_bufferoffset = 0;
11930 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)
11932 if ((f = DotProduct(n, lightdir)) > 0)
11933 VectorMA(ambientcolor, f, diffusecolor, c);
11935 VectorCopy(ambientcolor, c);
11942 *applycolor = false;
11946 *r = ambientcolor[0];
11947 *g = ambientcolor[1];
11948 *b = ambientcolor[2];
11949 rsurface.passcolor4f = NULL;
11950 rsurface.passcolor4f_vertexbuffer = 0;
11951 rsurface.passcolor4f_bufferoffset = 0;
11955 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11957 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
11958 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
11959 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11960 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11961 GL_Color(r, g, b, a);
11965 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
11971 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
11973 f = 1 - RSurf_FogVertex(v);
11981 void RSurf_SetupDepthAndCulling(void)
11983 // submodels are biased to avoid z-fighting with world surfaces that they
11984 // may be exactly overlapping (avoids z-fighting artifacts on certain
11985 // doors and things in Quake maps)
11986 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
11987 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
11988 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
11989 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11992 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11994 // transparent sky would be ridiculous
11995 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11997 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11998 skyrenderlater = true;
11999 RSurf_SetupDepthAndCulling();
12000 GL_DepthMask(true);
12001 // LordHavoc: HalfLife maps have freaky skypolys so don't use
12002 // skymasking on them, and Quake3 never did sky masking (unlike
12003 // software Quake and software Quake2), so disable the sky masking
12004 // in Quake3 maps as it causes problems with q3map2 sky tricks,
12005 // and skymasking also looks very bad when noclipping outside the
12006 // level, so don't use it then either.
12007 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12009 R_Mesh_ResetTextureState();
12010 if (skyrendermasked)
12012 R_SetupShader_DepthOrShadow();
12013 // depth-only (masking)
12014 GL_ColorMask(0,0,0,0);
12015 // just to make sure that braindead drivers don't draw
12016 // anything despite that colormask...
12017 GL_BlendFunc(GL_ZERO, GL_ONE);
12018 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12019 if (rsurface.batchvertex3fbuffer)
12020 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12022 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12026 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12028 GL_BlendFunc(GL_ONE, GL_ZERO);
12029 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12030 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12031 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12034 if (skyrendermasked)
12035 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12037 R_Mesh_ResetTextureState();
12038 GL_Color(1, 1, 1, 1);
12041 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12042 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12043 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12045 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12049 // render screenspace normalmap to texture
12050 GL_DepthMask(true);
12051 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12056 // bind lightmap texture
12058 // water/refraction/reflection/camera surfaces have to be handled specially
12059 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
12061 int start, end, startplaneindex;
12062 for (start = 0;start < texturenumsurfaces;start = end)
12064 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12065 if(startplaneindex < 0)
12067 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
12068 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
12072 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12074 // now that we have a batch using the same planeindex, render it
12075 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
12077 // render water or distortion background
12078 GL_DepthMask(true);
12079 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));
12081 // blend surface on top
12082 GL_DepthMask(false);
12083 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12086 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
12088 // render surface with reflection texture as input
12089 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12090 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));
12097 // render surface batch normally
12098 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12099 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12103 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12105 // OpenGL 1.3 path - anything not completely ancient
12106 qboolean applycolor;
12109 const texturelayer_t *layer;
12110 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);
12111 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12113 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12116 int layertexrgbscale;
12117 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12119 if (layerindex == 0)
12120 GL_AlphaTest(true);
12123 GL_AlphaTest(false);
12124 GL_DepthFunc(GL_EQUAL);
12127 GL_DepthMask(layer->depthmask && writedepth);
12128 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12129 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12131 layertexrgbscale = 4;
12132 VectorScale(layer->color, 0.25f, layercolor);
12134 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12136 layertexrgbscale = 2;
12137 VectorScale(layer->color, 0.5f, layercolor);
12141 layertexrgbscale = 1;
12142 VectorScale(layer->color, 1.0f, layercolor);
12144 layercolor[3] = layer->color[3];
12145 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12146 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12147 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12148 switch (layer->type)
12150 case TEXTURELAYERTYPE_LITTEXTURE:
12151 // single-pass lightmapped texture with 2x rgbscale
12152 R_Mesh_TexBind(0, r_texture_white);
12153 R_Mesh_TexMatrix(0, NULL);
12154 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12155 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12156 R_Mesh_TexBind(1, layer->texture);
12157 R_Mesh_TexMatrix(1, &layer->texmatrix);
12158 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12159 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12160 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12161 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12162 else if (FAKELIGHT_ENABLED)
12163 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12164 else if (rsurface.uselightmaptexture)
12165 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12167 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12169 case TEXTURELAYERTYPE_TEXTURE:
12170 // singletexture unlit texture with transparency support
12171 R_Mesh_TexBind(0, layer->texture);
12172 R_Mesh_TexMatrix(0, &layer->texmatrix);
12173 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12174 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12175 R_Mesh_TexBind(1, 0);
12176 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12177 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12179 case TEXTURELAYERTYPE_FOG:
12180 // singletexture fogging
12181 if (layer->texture)
12183 R_Mesh_TexBind(0, layer->texture);
12184 R_Mesh_TexMatrix(0, &layer->texmatrix);
12185 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12186 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12190 R_Mesh_TexBind(0, 0);
12191 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12193 R_Mesh_TexBind(1, 0);
12194 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12195 // generate a color array for the fog pass
12196 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12197 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12201 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12204 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12206 GL_DepthFunc(GL_LEQUAL);
12207 GL_AlphaTest(false);
12211 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12213 // OpenGL 1.1 - crusty old voodoo path
12216 const texturelayer_t *layer;
12217 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);
12218 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12220 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12222 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12224 if (layerindex == 0)
12225 GL_AlphaTest(true);
12228 GL_AlphaTest(false);
12229 GL_DepthFunc(GL_EQUAL);
12232 GL_DepthMask(layer->depthmask && writedepth);
12233 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12234 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12235 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12236 switch (layer->type)
12238 case TEXTURELAYERTYPE_LITTEXTURE:
12239 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12241 // two-pass lit texture with 2x rgbscale
12242 // first the lightmap pass
12243 R_Mesh_TexBind(0, r_texture_white);
12244 R_Mesh_TexMatrix(0, NULL);
12245 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12246 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12247 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12248 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12249 else if (FAKELIGHT_ENABLED)
12250 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12251 else if (rsurface.uselightmaptexture)
12252 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12254 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12255 // then apply the texture to it
12256 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12257 R_Mesh_TexBind(0, layer->texture);
12258 R_Mesh_TexMatrix(0, &layer->texmatrix);
12259 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12260 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12261 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);
12265 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12266 R_Mesh_TexBind(0, layer->texture);
12267 R_Mesh_TexMatrix(0, &layer->texmatrix);
12268 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12269 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12270 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12271 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);
12273 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);
12276 case TEXTURELAYERTYPE_TEXTURE:
12277 // singletexture unlit texture with transparency support
12278 R_Mesh_TexBind(0, layer->texture);
12279 R_Mesh_TexMatrix(0, &layer->texmatrix);
12280 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12281 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12282 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);
12284 case TEXTURELAYERTYPE_FOG:
12285 // singletexture fogging
12286 if (layer->texture)
12288 R_Mesh_TexBind(0, layer->texture);
12289 R_Mesh_TexMatrix(0, &layer->texmatrix);
12290 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12291 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12295 R_Mesh_TexBind(0, 0);
12296 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12298 // generate a color array for the fog pass
12299 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12300 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12304 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12307 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12309 GL_DepthFunc(GL_LEQUAL);
12310 GL_AlphaTest(false);
12314 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12318 r_vertexgeneric_t *batchvertex;
12321 // R_Mesh_ResetTextureState();
12322 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12324 if(rsurface.texture && rsurface.texture->currentskinframe)
12326 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12327 c[3] *= rsurface.texture->currentalpha;
12337 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12339 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12340 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12341 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12344 // brighten it up (as texture value 127 means "unlit")
12345 c[0] *= 2 * r_refdef.view.colorscale;
12346 c[1] *= 2 * r_refdef.view.colorscale;
12347 c[2] *= 2 * r_refdef.view.colorscale;
12349 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12350 c[3] *= r_wateralpha.value;
12352 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12354 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12355 GL_DepthMask(false);
12357 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12359 GL_BlendFunc(GL_ONE, GL_ONE);
12360 GL_DepthMask(false);
12362 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12364 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12365 GL_DepthMask(false);
12367 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12369 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12370 GL_DepthMask(false);
12374 GL_BlendFunc(GL_ONE, GL_ZERO);
12375 GL_DepthMask(writedepth);
12378 if (r_showsurfaces.integer == 3)
12380 rsurface.passcolor4f = NULL;
12382 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12384 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12386 rsurface.passcolor4f = NULL;
12387 rsurface.passcolor4f_vertexbuffer = 0;
12388 rsurface.passcolor4f_bufferoffset = 0;
12390 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12392 qboolean applycolor = true;
12395 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12397 r_refdef.lightmapintensity = 1;
12398 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12399 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12401 else if (FAKELIGHT_ENABLED)
12403 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12405 r_refdef.lightmapintensity = r_fakelight_intensity.value;
12406 RSurf_DrawBatch_GL11_ApplyFakeLight();
12407 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12411 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12413 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12414 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12415 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12418 if(!rsurface.passcolor4f)
12419 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12421 RSurf_DrawBatch_GL11_ApplyAmbient();
12422 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12423 if(r_refdef.fogenabled)
12424 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12425 RSurf_DrawBatch_GL11_ClampColor();
12427 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12428 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12431 else if (!r_refdef.view.showdebug)
12433 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12434 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12435 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12437 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12438 Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12440 R_Mesh_PrepareVertices_Generic_Unlock();
12443 else if (r_showsurfaces.integer == 4)
12445 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12446 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12447 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12449 unsigned char c = vi << 3;
12450 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12451 Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12453 R_Mesh_PrepareVertices_Generic_Unlock();
12456 else if (r_showsurfaces.integer == 2)
12459 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12460 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12461 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12463 unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12464 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12465 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12466 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12467 Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12468 Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12469 Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12471 R_Mesh_PrepareVertices_Generic_Unlock();
12472 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12476 int texturesurfaceindex;
12478 const msurface_t *surface;
12479 unsigned char surfacecolor4ub[4];
12480 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12481 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12483 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12485 surface = texturesurfacelist[texturesurfaceindex];
12486 k = (int)(((size_t)surface) / sizeof(msurface_t));
12487 Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
12488 for (j = 0;j < surface->num_vertices;j++)
12490 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12491 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
12495 R_Mesh_PrepareVertices_Generic_Unlock();
12500 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12503 RSurf_SetupDepthAndCulling();
12504 if (r_showsurfaces.integer)
12506 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12509 switch (vid.renderpath)
12511 case RENDERPATH_GL20:
12512 case RENDERPATH_D3D9:
12513 case RENDERPATH_D3D10:
12514 case RENDERPATH_D3D11:
12515 case RENDERPATH_SOFT:
12516 case RENDERPATH_GLES2:
12517 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12519 case RENDERPATH_GL13:
12520 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12522 case RENDERPATH_GL11:
12523 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12529 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12532 RSurf_SetupDepthAndCulling();
12533 if (r_showsurfaces.integer)
12535 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12538 switch (vid.renderpath)
12540 case RENDERPATH_GL20:
12541 case RENDERPATH_D3D9:
12542 case RENDERPATH_D3D10:
12543 case RENDERPATH_D3D11:
12544 case RENDERPATH_SOFT:
12545 case RENDERPATH_GLES2:
12546 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12548 case RENDERPATH_GL13:
12549 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12551 case RENDERPATH_GL11:
12552 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12558 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12561 int texturenumsurfaces, endsurface;
12562 texture_t *texture;
12563 const msurface_t *surface;
12564 #define MAXBATCH_TRANSPARENTSURFACES 256
12565 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
12567 // if the model is static it doesn't matter what value we give for
12568 // wantnormals and wanttangents, so this logic uses only rules applicable
12569 // to a model, knowing that they are meaningless otherwise
12570 if (ent == r_refdef.scene.worldentity)
12571 RSurf_ActiveWorldEntity();
12572 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12573 RSurf_ActiveModelEntity(ent, false, false, false);
12576 switch (vid.renderpath)
12578 case RENDERPATH_GL20:
12579 case RENDERPATH_D3D9:
12580 case RENDERPATH_D3D10:
12581 case RENDERPATH_D3D11:
12582 case RENDERPATH_SOFT:
12583 case RENDERPATH_GLES2:
12584 RSurf_ActiveModelEntity(ent, true, true, false);
12586 case RENDERPATH_GL13:
12587 case RENDERPATH_GL11:
12588 RSurf_ActiveModelEntity(ent, true, false, false);
12593 if (r_transparentdepthmasking.integer)
12595 qboolean setup = false;
12596 for (i = 0;i < numsurfaces;i = j)
12599 surface = rsurface.modelsurfaces + surfacelist[i];
12600 texture = surface->texture;
12601 rsurface.texture = R_GetCurrentTexture(texture);
12602 rsurface.lightmaptexture = NULL;
12603 rsurface.deluxemaptexture = NULL;
12604 rsurface.uselightmaptexture = false;
12605 // scan ahead until we find a different texture
12606 endsurface = min(i + 1024, numsurfaces);
12607 texturenumsurfaces = 0;
12608 texturesurfacelist[texturenumsurfaces++] = surface;
12609 for (;j < endsurface;j++)
12611 surface = rsurface.modelsurfaces + surfacelist[j];
12612 if (texture != surface->texture)
12614 texturesurfacelist[texturenumsurfaces++] = surface;
12616 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
12618 // render the range of surfaces as depth
12622 GL_ColorMask(0,0,0,0);
12624 GL_DepthTest(true);
12625 GL_BlendFunc(GL_ONE, GL_ZERO);
12626 GL_DepthMask(true);
12627 // R_Mesh_ResetTextureState();
12628 R_SetupShader_DepthOrShadow();
12630 RSurf_SetupDepthAndCulling();
12631 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
12632 if (rsurface.batchvertex3fbuffer)
12633 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12635 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12639 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12642 for (i = 0;i < numsurfaces;i = j)
12645 surface = rsurface.modelsurfaces + surfacelist[i];
12646 texture = surface->texture;
12647 rsurface.texture = R_GetCurrentTexture(texture);
12648 // scan ahead until we find a different texture
12649 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
12650 texturenumsurfaces = 0;
12651 texturesurfacelist[texturenumsurfaces++] = surface;
12652 if(FAKELIGHT_ENABLED)
12654 rsurface.lightmaptexture = NULL;
12655 rsurface.deluxemaptexture = NULL;
12656 rsurface.uselightmaptexture = false;
12657 for (;j < endsurface;j++)
12659 surface = rsurface.modelsurfaces + surfacelist[j];
12660 if (texture != surface->texture)
12662 texturesurfacelist[texturenumsurfaces++] = surface;
12667 rsurface.lightmaptexture = surface->lightmaptexture;
12668 rsurface.deluxemaptexture = surface->deluxemaptexture;
12669 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
12670 for (;j < endsurface;j++)
12672 surface = rsurface.modelsurfaces + surfacelist[j];
12673 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
12675 texturesurfacelist[texturenumsurfaces++] = surface;
12678 // render the range of surfaces
12679 if (ent == r_refdef.scene.worldentity)
12680 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12682 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12684 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12687 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
12689 // transparent surfaces get pushed off into the transparent queue
12690 int surfacelistindex;
12691 const msurface_t *surface;
12692 vec3_t tempcenter, center;
12693 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
12695 surface = texturesurfacelist[surfacelistindex];
12696 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
12697 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
12698 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
12699 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
12700 if (queueentity->transparent_offset) // transparent offset
12702 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
12703 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
12704 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
12706 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
12710 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12712 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
12714 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
12716 RSurf_SetupDepthAndCulling();
12717 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
12718 if (rsurface.batchvertex3fbuffer)
12719 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12721 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12725 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
12727 const entity_render_t *queueentity = r_refdef.scene.worldentity;
12730 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12733 if (!rsurface.texture->currentnumlayers)
12735 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12736 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12738 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12740 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12741 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12742 else if (!rsurface.texture->currentnumlayers)
12744 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12746 // in the deferred case, transparent surfaces were queued during prepass
12747 if (!r_shadow_usingdeferredprepass)
12748 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12752 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12753 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12758 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12761 texture_t *texture;
12762 R_FrameData_SetMark();
12763 // break the surface list down into batches by texture and use of lightmapping
12764 for (i = 0;i < numsurfaces;i = j)
12767 // texture is the base texture pointer, rsurface.texture is the
12768 // current frame/skin the texture is directing us to use (for example
12769 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12770 // use skin 1 instead)
12771 texture = surfacelist[i]->texture;
12772 rsurface.texture = R_GetCurrentTexture(texture);
12773 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12775 // if this texture is not the kind we want, skip ahead to the next one
12776 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12780 if(FAKELIGHT_ENABLED || depthonly || prepass)
12782 rsurface.lightmaptexture = NULL;
12783 rsurface.deluxemaptexture = NULL;
12784 rsurface.uselightmaptexture = false;
12785 // simply scan ahead until we find a different texture or lightmap state
12786 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12791 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12792 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12793 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
12794 // simply scan ahead until we find a different texture or lightmap state
12795 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12798 // render the range of surfaces
12799 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
12801 R_FrameData_ReturnToMark();
12804 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
12808 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12811 if (!rsurface.texture->currentnumlayers)
12813 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12814 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12816 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12818 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12819 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12820 else if (!rsurface.texture->currentnumlayers)
12822 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12824 // in the deferred case, transparent surfaces were queued during prepass
12825 if (!r_shadow_usingdeferredprepass)
12826 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12830 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12831 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12836 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12839 texture_t *texture;
12840 R_FrameData_SetMark();
12841 // break the surface list down into batches by texture and use of lightmapping
12842 for (i = 0;i < numsurfaces;i = j)
12845 // texture is the base texture pointer, rsurface.texture is the
12846 // current frame/skin the texture is directing us to use (for example
12847 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12848 // use skin 1 instead)
12849 texture = surfacelist[i]->texture;
12850 rsurface.texture = R_GetCurrentTexture(texture);
12851 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12853 // if this texture is not the kind we want, skip ahead to the next one
12854 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12858 if(FAKELIGHT_ENABLED || depthonly || prepass)
12860 rsurface.lightmaptexture = NULL;
12861 rsurface.deluxemaptexture = NULL;
12862 rsurface.uselightmaptexture = false;
12863 // simply scan ahead until we find a different texture or lightmap state
12864 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12869 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12870 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12871 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
12872 // simply scan ahead until we find a different texture or lightmap state
12873 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12876 // render the range of surfaces
12877 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
12879 R_FrameData_ReturnToMark();
12882 float locboxvertex3f[6*4*3] =
12884 1,0,1, 1,0,0, 1,1,0, 1,1,1,
12885 0,1,1, 0,1,0, 0,0,0, 0,0,1,
12886 1,1,1, 1,1,0, 0,1,0, 0,1,1,
12887 0,0,1, 0,0,0, 1,0,0, 1,0,1,
12888 0,0,1, 1,0,1, 1,1,1, 0,1,1,
12889 1,0,0, 0,0,0, 0,1,0, 1,1,0
12892 unsigned short locboxelements[6*2*3] =
12897 12,13,14, 12,14,15,
12898 16,17,18, 16,18,19,
12902 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12905 cl_locnode_t *loc = (cl_locnode_t *)ent;
12907 float vertex3f[6*4*3];
12909 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12910 GL_DepthMask(false);
12911 GL_DepthRange(0, 1);
12912 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12913 GL_DepthTest(true);
12914 GL_CullFace(GL_NONE);
12915 R_EntityMatrix(&identitymatrix);
12917 // R_Mesh_ResetTextureState();
12919 i = surfacelist[0];
12920 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12921 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12922 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12923 surfacelist[0] < 0 ? 0.5f : 0.125f);
12925 if (VectorCompare(loc->mins, loc->maxs))
12927 VectorSet(size, 2, 2, 2);
12928 VectorMA(loc->mins, -0.5f, size, mins);
12932 VectorCopy(loc->mins, mins);
12933 VectorSubtract(loc->maxs, loc->mins, size);
12936 for (i = 0;i < 6*4*3;)
12937 for (j = 0;j < 3;j++, i++)
12938 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
12940 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
12941 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12942 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
12945 void R_DrawLocs(void)
12948 cl_locnode_t *loc, *nearestloc;
12950 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
12951 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
12953 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
12954 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
12958 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
12960 if (decalsystem->decals)
12961 Mem_Free(decalsystem->decals);
12962 memset(decalsystem, 0, sizeof(*decalsystem));
12965 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)
12968 tridecal_t *decals;
12971 // expand or initialize the system
12972 if (decalsystem->maxdecals <= decalsystem->numdecals)
12974 decalsystem_t old = *decalsystem;
12975 qboolean useshortelements;
12976 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
12977 useshortelements = decalsystem->maxdecals * 3 <= 65536;
12978 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)));
12979 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
12980 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
12981 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
12982 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
12983 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
12984 if (decalsystem->numdecals)
12985 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
12987 Mem_Free(old.decals);
12988 for (i = 0;i < decalsystem->maxdecals*3;i++)
12989 decalsystem->element3i[i] = i;
12990 if (useshortelements)
12991 for (i = 0;i < decalsystem->maxdecals*3;i++)
12992 decalsystem->element3s[i] = i;
12995 // grab a decal and search for another free slot for the next one
12996 decals = decalsystem->decals;
12997 decal = decalsystem->decals + (i = decalsystem->freedecal++);
12998 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13000 decalsystem->freedecal = i;
13001 if (decalsystem->numdecals <= i)
13002 decalsystem->numdecals = i + 1;
13004 // initialize the decal
13006 decal->triangleindex = triangleindex;
13007 decal->surfaceindex = surfaceindex;
13008 decal->decalsequence = decalsequence;
13009 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13010 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13011 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13012 decal->color4ub[0][3] = 255;
13013 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13014 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13015 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13016 decal->color4ub[1][3] = 255;
13017 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13018 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13019 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13020 decal->color4ub[2][3] = 255;
13021 decal->vertex3f[0][0] = v0[0];
13022 decal->vertex3f[0][1] = v0[1];
13023 decal->vertex3f[0][2] = v0[2];
13024 decal->vertex3f[1][0] = v1[0];
13025 decal->vertex3f[1][1] = v1[1];
13026 decal->vertex3f[1][2] = v1[2];
13027 decal->vertex3f[2][0] = v2[0];
13028 decal->vertex3f[2][1] = v2[1];
13029 decal->vertex3f[2][2] = v2[2];
13030 decal->texcoord2f[0][0] = t0[0];
13031 decal->texcoord2f[0][1] = t0[1];
13032 decal->texcoord2f[1][0] = t1[0];
13033 decal->texcoord2f[1][1] = t1[1];
13034 decal->texcoord2f[2][0] = t2[0];
13035 decal->texcoord2f[2][1] = t2[1];
13038 extern cvar_t cl_decals_bias;
13039 extern cvar_t cl_decals_models;
13040 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13041 // baseparms, parms, temps
13042 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)
13047 const float *vertex3f;
13049 float points[2][9][3];
13056 e = rsurface.modelelement3i + 3*triangleindex;
13058 vertex3f = rsurface.modelvertex3f;
13060 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13062 index = 3*e[cornerindex];
13063 VectorCopy(vertex3f + index, v[cornerindex]);
13066 //TriangleNormal(v[0], v[1], v[2], normal);
13067 //if (DotProduct(normal, localnormal) < 0.0f)
13069 // clip by each of the box planes formed from the projection matrix
13070 // if anything survives, we emit the decal
13071 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]);
13074 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]);
13077 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]);
13080 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]);
13083 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]);
13086 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]);
13089 // some part of the triangle survived, so we have to accept it...
13092 // dynamic always uses the original triangle
13094 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13096 index = 3*e[cornerindex];
13097 VectorCopy(vertex3f + index, v[cornerindex]);
13100 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13102 // convert vertex positions to texcoords
13103 Matrix4x4_Transform(projection, v[cornerindex], temp);
13104 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13105 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13106 // calculate distance fade from the projection origin
13107 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13108 f = bound(0.0f, f, 1.0f);
13109 c[cornerindex][0] = r * f;
13110 c[cornerindex][1] = g * f;
13111 c[cornerindex][2] = b * f;
13112 c[cornerindex][3] = 1.0f;
13113 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13116 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);
13118 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13119 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);
13121 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)
13123 matrix4x4_t projection;
13124 decalsystem_t *decalsystem;
13127 const msurface_t *surface;
13128 const msurface_t *surfaces;
13129 const int *surfacelist;
13130 const texture_t *texture;
13132 int numsurfacelist;
13133 int surfacelistindex;
13136 float localorigin[3];
13137 float localnormal[3];
13138 float localmins[3];
13139 float localmaxs[3];
13142 float planes[6][4];
13145 int bih_triangles_count;
13146 int bih_triangles[256];
13147 int bih_surfaces[256];
13149 decalsystem = &ent->decalsystem;
13150 model = ent->model;
13151 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13153 R_DecalSystem_Reset(&ent->decalsystem);
13157 if (!model->brush.data_leafs && !cl_decals_models.integer)
13159 if (decalsystem->model)
13160 R_DecalSystem_Reset(decalsystem);
13164 if (decalsystem->model != model)
13165 R_DecalSystem_Reset(decalsystem);
13166 decalsystem->model = model;
13168 RSurf_ActiveModelEntity(ent, false, false, false);
13170 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13171 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13172 VectorNormalize(localnormal);
13173 localsize = worldsize*rsurface.inversematrixscale;
13174 localmins[0] = localorigin[0] - localsize;
13175 localmins[1] = localorigin[1] - localsize;
13176 localmins[2] = localorigin[2] - localsize;
13177 localmaxs[0] = localorigin[0] + localsize;
13178 localmaxs[1] = localorigin[1] + localsize;
13179 localmaxs[2] = localorigin[2] + localsize;
13181 //VectorCopy(localnormal, planes[4]);
13182 //VectorVectors(planes[4], planes[2], planes[0]);
13183 AnglesFromVectors(angles, localnormal, NULL, false);
13184 AngleVectors(angles, planes[0], planes[2], planes[4]);
13185 VectorNegate(planes[0], planes[1]);
13186 VectorNegate(planes[2], planes[3]);
13187 VectorNegate(planes[4], planes[5]);
13188 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13189 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13190 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13191 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13192 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13193 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13198 matrix4x4_t forwardprojection;
13199 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13200 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13205 float projectionvector[4][3];
13206 VectorScale(planes[0], ilocalsize, projectionvector[0]);
13207 VectorScale(planes[2], ilocalsize, projectionvector[1]);
13208 VectorScale(planes[4], ilocalsize, projectionvector[2]);
13209 projectionvector[0][0] = planes[0][0] * ilocalsize;
13210 projectionvector[0][1] = planes[1][0] * ilocalsize;
13211 projectionvector[0][2] = planes[2][0] * ilocalsize;
13212 projectionvector[1][0] = planes[0][1] * ilocalsize;
13213 projectionvector[1][1] = planes[1][1] * ilocalsize;
13214 projectionvector[1][2] = planes[2][1] * ilocalsize;
13215 projectionvector[2][0] = planes[0][2] * ilocalsize;
13216 projectionvector[2][1] = planes[1][2] * ilocalsize;
13217 projectionvector[2][2] = planes[2][2] * ilocalsize;
13218 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13219 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13220 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13221 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13225 dynamic = model->surfmesh.isanimated;
13226 numsurfacelist = model->nummodelsurfaces;
13227 surfacelist = model->sortedmodelsurfaces;
13228 surfaces = model->data_surfaces;
13231 bih_triangles_count = -1;
13234 if(model->render_bih.numleafs)
13235 bih = &model->render_bih;
13236 else if(model->collision_bih.numleafs)
13237 bih = &model->collision_bih;
13240 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13241 if(bih_triangles_count == 0)
13243 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13245 if(bih_triangles_count > 0)
13247 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13249 surfaceindex = bih_surfaces[triangleindex];
13250 surface = surfaces + surfaceindex;
13251 texture = surface->texture;
13252 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13254 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13256 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13261 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13263 surfaceindex = surfacelist[surfacelistindex];
13264 surface = surfaces + surfaceindex;
13265 // check cull box first because it rejects more than any other check
13266 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13268 // skip transparent surfaces
13269 texture = surface->texture;
13270 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13272 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13274 numtriangles = surface->num_triangles;
13275 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13276 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13281 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13282 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)
13284 int renderentityindex;
13285 float worldmins[3];
13286 float worldmaxs[3];
13287 entity_render_t *ent;
13289 if (!cl_decals_newsystem.integer)
13292 worldmins[0] = worldorigin[0] - worldsize;
13293 worldmins[1] = worldorigin[1] - worldsize;
13294 worldmins[2] = worldorigin[2] - worldsize;
13295 worldmaxs[0] = worldorigin[0] + worldsize;
13296 worldmaxs[1] = worldorigin[1] + worldsize;
13297 worldmaxs[2] = worldorigin[2] + worldsize;
13299 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13301 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13303 ent = r_refdef.scene.entities[renderentityindex];
13304 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13307 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13311 typedef struct r_decalsystem_splatqueue_s
13313 vec3_t worldorigin;
13314 vec3_t worldnormal;
13320 r_decalsystem_splatqueue_t;
13322 int r_decalsystem_numqueued = 0;
13323 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13325 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)
13327 r_decalsystem_splatqueue_t *queue;
13329 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13332 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13333 VectorCopy(worldorigin, queue->worldorigin);
13334 VectorCopy(worldnormal, queue->worldnormal);
13335 Vector4Set(queue->color, r, g, b, a);
13336 Vector4Set(queue->tcrange, s1, t1, s2, t2);
13337 queue->worldsize = worldsize;
13338 queue->decalsequence = cl.decalsequence++;
13341 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13344 r_decalsystem_splatqueue_t *queue;
13346 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13347 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);
13348 r_decalsystem_numqueued = 0;
13351 extern cvar_t cl_decals_max;
13352 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13355 decalsystem_t *decalsystem = &ent->decalsystem;
13362 if (!decalsystem->numdecals)
13365 if (r_showsurfaces.integer)
13368 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13370 R_DecalSystem_Reset(decalsystem);
13374 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13375 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13377 if (decalsystem->lastupdatetime)
13378 frametime = (cl.time - decalsystem->lastupdatetime);
13381 decalsystem->lastupdatetime = cl.time;
13382 decal = decalsystem->decals;
13383 numdecals = decalsystem->numdecals;
13385 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13387 if (decal->color4ub[0][3])
13389 decal->lived += frametime;
13390 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13392 memset(decal, 0, sizeof(*decal));
13393 if (decalsystem->freedecal > i)
13394 decalsystem->freedecal = i;
13398 decal = decalsystem->decals;
13399 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13402 // collapse the array by shuffling the tail decals into the gaps
13405 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13406 decalsystem->freedecal++;
13407 if (decalsystem->freedecal == numdecals)
13409 decal[decalsystem->freedecal] = decal[--numdecals];
13412 decalsystem->numdecals = numdecals;
13414 if (numdecals <= 0)
13416 // if there are no decals left, reset decalsystem
13417 R_DecalSystem_Reset(decalsystem);
13421 extern skinframe_t *decalskinframe;
13422 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13425 decalsystem_t *decalsystem = &ent->decalsystem;
13434 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13437 numdecals = decalsystem->numdecals;
13441 if (r_showsurfaces.integer)
13444 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13446 R_DecalSystem_Reset(decalsystem);
13450 // if the model is static it doesn't matter what value we give for
13451 // wantnormals and wanttangents, so this logic uses only rules applicable
13452 // to a model, knowing that they are meaningless otherwise
13453 if (ent == r_refdef.scene.worldentity)
13454 RSurf_ActiveWorldEntity();
13456 RSurf_ActiveModelEntity(ent, false, false, false);
13458 decalsystem->lastupdatetime = cl.time;
13459 decal = decalsystem->decals;
13461 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13463 // update vertex positions for animated models
13464 v3f = decalsystem->vertex3f;
13465 c4f = decalsystem->color4f;
13466 t2f = decalsystem->texcoord2f;
13467 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13469 if (!decal->color4ub[0][3])
13472 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13475 // update color values for fading decals
13476 if (decal->lived >= cl_decals_time.value)
13478 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13479 alpha *= (1.0f/255.0f);
13482 alpha = 1.0f/255.0f;
13484 c4f[ 0] = decal->color4ub[0][0] * alpha;
13485 c4f[ 1] = decal->color4ub[0][1] * alpha;
13486 c4f[ 2] = decal->color4ub[0][2] * alpha;
13488 c4f[ 4] = decal->color4ub[1][0] * alpha;
13489 c4f[ 5] = decal->color4ub[1][1] * alpha;
13490 c4f[ 6] = decal->color4ub[1][2] * alpha;
13492 c4f[ 8] = decal->color4ub[2][0] * alpha;
13493 c4f[ 9] = decal->color4ub[2][1] * alpha;
13494 c4f[10] = decal->color4ub[2][2] * alpha;
13497 t2f[0] = decal->texcoord2f[0][0];
13498 t2f[1] = decal->texcoord2f[0][1];
13499 t2f[2] = decal->texcoord2f[1][0];
13500 t2f[3] = decal->texcoord2f[1][1];
13501 t2f[4] = decal->texcoord2f[2][0];
13502 t2f[5] = decal->texcoord2f[2][1];
13504 // update vertex positions for animated models
13505 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13507 e = rsurface.modelelement3i + 3*decal->triangleindex;
13508 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
13509 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
13510 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
13514 VectorCopy(decal->vertex3f[0], v3f);
13515 VectorCopy(decal->vertex3f[1], v3f + 3);
13516 VectorCopy(decal->vertex3f[2], v3f + 6);
13519 if (r_refdef.fogenabled)
13521 alpha = RSurf_FogVertex(v3f);
13522 VectorScale(c4f, alpha, c4f);
13523 alpha = RSurf_FogVertex(v3f + 3);
13524 VectorScale(c4f + 4, alpha, c4f + 4);
13525 alpha = RSurf_FogVertex(v3f + 6);
13526 VectorScale(c4f + 8, alpha, c4f + 8);
13537 r_refdef.stats.drawndecals += numtris;
13539 // now render the decals all at once
13540 // (this assumes they all use one particle font texture!)
13541 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);
13542 // R_Mesh_ResetTextureState();
13543 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
13544 GL_DepthMask(false);
13545 GL_DepthRange(0, 1);
13546 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
13547 GL_DepthTest(true);
13548 GL_CullFace(GL_NONE);
13549 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
13550 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
13551 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
13555 static void R_DrawModelDecals(void)
13559 // fade faster when there are too many decals
13560 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13561 for (i = 0;i < r_refdef.scene.numentities;i++)
13562 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13564 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
13565 for (i = 0;i < r_refdef.scene.numentities;i++)
13566 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13567 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
13569 R_DecalSystem_ApplySplatEntitiesQueue();
13571 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13572 for (i = 0;i < r_refdef.scene.numentities;i++)
13573 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13575 r_refdef.stats.totaldecals += numdecals;
13577 if (r_showsurfaces.integer)
13580 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
13582 for (i = 0;i < r_refdef.scene.numentities;i++)
13584 if (!r_refdef.viewcache.entityvisible[i])
13586 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13587 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
13591 extern cvar_t mod_collision_bih;
13592 void R_DrawDebugModel(void)
13594 entity_render_t *ent = rsurface.entity;
13595 int i, j, k, l, flagsmask;
13596 const msurface_t *surface;
13597 dp_model_t *model = ent->model;
13600 switch(vid.renderpath)
13602 case RENDERPATH_GL11:
13603 case RENDERPATH_GL13:
13604 case RENDERPATH_GL20:
13606 case RENDERPATH_D3D9:
13607 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13609 case RENDERPATH_D3D10:
13610 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13612 case RENDERPATH_D3D11:
13613 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13615 case RENDERPATH_SOFT:
13616 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13618 case RENDERPATH_GLES2:
13619 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13623 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
13625 // R_Mesh_ResetTextureState();
13626 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13627 GL_DepthRange(0, 1);
13628 GL_DepthTest(!r_showdisabledepthtest.integer);
13629 GL_DepthMask(false);
13630 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13632 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
13636 qboolean cullbox = ent == r_refdef.scene.worldentity;
13637 const q3mbrush_t *brush;
13638 const bih_t *bih = &model->collision_bih;
13639 const bih_leaf_t *bihleaf;
13640 float vertex3f[3][3];
13641 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
13643 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
13645 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
13647 switch (bihleaf->type)
13650 brush = model->brush.data_brushes + bihleaf->itemindex;
13651 if (brush->colbrushf && brush->colbrushf->numtriangles)
13653 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);
13654 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
13655 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
13658 case BIH_COLLISIONTRIANGLE:
13659 triangleindex = bihleaf->itemindex;
13660 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
13661 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
13662 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
13663 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);
13664 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13665 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13667 case BIH_RENDERTRIANGLE:
13668 triangleindex = bihleaf->itemindex;
13669 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
13670 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
13671 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
13672 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);
13673 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13674 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13680 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13682 if (r_showtris.integer || (r_shownormals.value != 0))
13684 if (r_showdisabledepthtest.integer)
13686 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13687 GL_DepthMask(false);
13691 GL_BlendFunc(GL_ONE, GL_ZERO);
13692 GL_DepthMask(true);
13694 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
13696 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
13698 rsurface.texture = R_GetCurrentTexture(surface->texture);
13699 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
13701 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
13702 if (r_showtris.value > 0)
13704 if (!rsurface.texture->currentlayers->depthmask)
13705 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
13706 else if (ent == r_refdef.scene.worldentity)
13707 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
13709 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
13710 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
13711 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
13713 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
13716 if (r_shownormals.value < 0)
13718 qglBegin(GL_LINES);
13719 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13721 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13722 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13723 qglVertex3f(v[0], v[1], v[2]);
13724 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
13725 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13726 qglVertex3f(v[0], v[1], v[2]);
13731 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
13733 qglBegin(GL_LINES);
13734 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13736 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13737 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13738 qglVertex3f(v[0], v[1], v[2]);
13739 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
13740 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13741 qglVertex3f(v[0], v[1], v[2]);
13745 qglBegin(GL_LINES);
13746 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13748 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13749 GL_Color(0, r_refdef.view.colorscale, 0, 1);
13750 qglVertex3f(v[0], v[1], v[2]);
13751 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
13752 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13753 qglVertex3f(v[0], v[1], v[2]);
13757 qglBegin(GL_LINES);
13758 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13760 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13761 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13762 qglVertex3f(v[0], v[1], v[2]);
13763 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
13764 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13765 qglVertex3f(v[0], v[1], v[2]);
13772 rsurface.texture = NULL;
13776 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
13777 int r_maxsurfacelist = 0;
13778 const msurface_t **r_surfacelist = NULL;
13779 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13781 int i, j, endj, flagsmask;
13782 dp_model_t *model = r_refdef.scene.worldmodel;
13783 msurface_t *surfaces;
13784 unsigned char *update;
13785 int numsurfacelist = 0;
13789 if (r_maxsurfacelist < model->num_surfaces)
13791 r_maxsurfacelist = model->num_surfaces;
13793 Mem_Free((msurface_t**)r_surfacelist);
13794 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13797 RSurf_ActiveWorldEntity();
13799 surfaces = model->data_surfaces;
13800 update = model->brushq1.lightmapupdateflags;
13802 // update light styles on this submodel
13803 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13805 model_brush_lightstyleinfo_t *style;
13806 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13808 if (style->value != r_refdef.scene.lightstylevalue[style->style])
13810 int *list = style->surfacelist;
13811 style->value = r_refdef.scene.lightstylevalue[style->style];
13812 for (j = 0;j < style->numsurfaces;j++)
13813 update[list[j]] = true;
13818 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13822 R_DrawDebugModel();
13823 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13827 rsurface.lightmaptexture = NULL;
13828 rsurface.deluxemaptexture = NULL;
13829 rsurface.uselightmaptexture = false;
13830 rsurface.texture = NULL;
13831 rsurface.rtlight = NULL;
13832 numsurfacelist = 0;
13833 // add visible surfaces to draw list
13834 for (i = 0;i < model->nummodelsurfaces;i++)
13836 j = model->sortedmodelsurfaces[i];
13837 if (r_refdef.viewcache.world_surfacevisible[j])
13838 r_surfacelist[numsurfacelist++] = surfaces + j;
13840 // update lightmaps if needed
13841 if (model->brushq1.firstrender)
13843 model->brushq1.firstrender = false;
13844 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13846 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13850 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13851 if (r_refdef.viewcache.world_surfacevisible[j])
13853 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13855 // don't do anything if there were no surfaces
13856 if (!numsurfacelist)
13858 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13861 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13863 // add to stats if desired
13864 if (r_speeds.integer && !skysurfaces && !depthonly)
13866 r_refdef.stats.world_surfaces += numsurfacelist;
13867 for (j = 0;j < numsurfacelist;j++)
13868 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
13871 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13874 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13876 int i, j, endj, flagsmask;
13877 dp_model_t *model = ent->model;
13878 msurface_t *surfaces;
13879 unsigned char *update;
13880 int numsurfacelist = 0;
13884 if (r_maxsurfacelist < model->num_surfaces)
13886 r_maxsurfacelist = model->num_surfaces;
13888 Mem_Free((msurface_t **)r_surfacelist);
13889 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13892 // if the model is static it doesn't matter what value we give for
13893 // wantnormals and wanttangents, so this logic uses only rules applicable
13894 // to a model, knowing that they are meaningless otherwise
13895 if (ent == r_refdef.scene.worldentity)
13896 RSurf_ActiveWorldEntity();
13897 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13898 RSurf_ActiveModelEntity(ent, false, false, false);
13900 RSurf_ActiveModelEntity(ent, true, true, true);
13901 else if (depthonly)
13903 switch (vid.renderpath)
13905 case RENDERPATH_GL20:
13906 case RENDERPATH_D3D9:
13907 case RENDERPATH_D3D10:
13908 case RENDERPATH_D3D11:
13909 case RENDERPATH_SOFT:
13910 case RENDERPATH_GLES2:
13911 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
13913 case RENDERPATH_GL13:
13914 case RENDERPATH_GL11:
13915 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
13921 switch (vid.renderpath)
13923 case RENDERPATH_GL20:
13924 case RENDERPATH_D3D9:
13925 case RENDERPATH_D3D10:
13926 case RENDERPATH_D3D11:
13927 case RENDERPATH_SOFT:
13928 case RENDERPATH_GLES2:
13929 RSurf_ActiveModelEntity(ent, true, true, false);
13931 case RENDERPATH_GL13:
13932 case RENDERPATH_GL11:
13933 RSurf_ActiveModelEntity(ent, true, false, false);
13938 surfaces = model->data_surfaces;
13939 update = model->brushq1.lightmapupdateflags;
13941 // update light styles
13942 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13944 model_brush_lightstyleinfo_t *style;
13945 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13947 if (style->value != r_refdef.scene.lightstylevalue[style->style])
13949 int *list = style->surfacelist;
13950 style->value = r_refdef.scene.lightstylevalue[style->style];
13951 for (j = 0;j < style->numsurfaces;j++)
13952 update[list[j]] = true;
13957 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13961 R_DrawDebugModel();
13962 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13966 rsurface.lightmaptexture = NULL;
13967 rsurface.deluxemaptexture = NULL;
13968 rsurface.uselightmaptexture = false;
13969 rsurface.texture = NULL;
13970 rsurface.rtlight = NULL;
13971 numsurfacelist = 0;
13972 // add visible surfaces to draw list
13973 for (i = 0;i < model->nummodelsurfaces;i++)
13974 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
13975 // don't do anything if there were no surfaces
13976 if (!numsurfacelist)
13978 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13981 // update lightmaps if needed
13985 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13990 R_BuildLightMap(ent, surfaces + j);
13995 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13997 R_BuildLightMap(ent, surfaces + j);
13998 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14000 // add to stats if desired
14001 if (r_speeds.integer && !skysurfaces && !depthonly)
14003 r_refdef.stats.entities_surfaces += numsurfacelist;
14004 for (j = 0;j < numsurfacelist;j++)
14005 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14008 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14011 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14013 static texture_t texture;
14014 static msurface_t surface;
14015 const msurface_t *surfacelist = &surface;
14017 // fake enough texture and surface state to render this geometry
14019 texture.update_lastrenderframe = -1; // regenerate this texture
14020 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14021 texture.currentskinframe = skinframe;
14022 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14023 texture.offsetmapping = OFFSETMAPPING_OFF;
14024 texture.offsetscale = 1;
14025 texture.specularscalemod = 1;
14026 texture.specularpowermod = 1;
14028 surface.texture = &texture;
14029 surface.num_triangles = numtriangles;
14030 surface.num_firsttriangle = firsttriangle;
14031 surface.num_vertices = numvertices;
14032 surface.num_firstvertex = firstvertex;
14035 rsurface.texture = R_GetCurrentTexture(surface.texture);
14036 rsurface.lightmaptexture = NULL;
14037 rsurface.deluxemaptexture = NULL;
14038 rsurface.uselightmaptexture = false;
14039 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14042 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)
14044 static msurface_t surface;
14045 const msurface_t *surfacelist = &surface;
14047 // fake enough texture and surface state to render this geometry
14048 surface.texture = texture;
14049 surface.num_triangles = numtriangles;
14050 surface.num_firsttriangle = firsttriangle;
14051 surface.num_vertices = numvertices;
14052 surface.num_firstvertex = firstvertex;
14055 rsurface.texture = R_GetCurrentTexture(surface.texture);
14056 rsurface.lightmaptexture = NULL;
14057 rsurface.deluxemaptexture = NULL;
14058 rsurface.uselightmaptexture = false;
14059 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);