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"
1061 "#ifdef MODE_DEFERREDBOUNCELIGHT\n"
1062 "varying highp vec4 ModelViewPosition;\n"
1063 "varying highp vec4 LightOriginInvRadius;\n"
1064 "varying mediump vec4 LightColor;\n"
1067 "#ifdef MODE_LIGHTSOURCE\n"
1068 "uniform highp vec3 LightPosition;\n"
1070 "uniform highp vec3 EyePosition;\n"
1071 "#ifdef MODE_LIGHTDIRECTION\n"
1072 "uniform highp vec3 LightDir;\n"
1074 "uniform highp vec4 FogPlane;\n"
1076 "#ifdef USESHADOWMAPORTHO\n"
1077 "varying mediump vec3 ShadowMapTC;\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"
1131 "#ifdef MODE_DEFERREDBOUNCELIGHT\n"
1132 "uniform sampler2D Texture_ScreenDepth;\n"
1135 "uniform lowp vec3 Color_Pants;\n"
1136 "uniform lowp vec3 Color_Shirt;\n"
1137 "uniform lowp vec3 FogColor;\n"
1140 "uniform highp float FogRangeRecip;\n"
1141 "uniform highp float FogPlaneViewDist;\n"
1142 "uniform highp float FogHeightFade;\n"
1143 "vec3 FogVertex(vec3 surfacecolor)\n"
1145 " vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1146 " float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1148 "#ifdef USEFOGHEIGHTTEXTURE\n"
1149 " vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1150 " fogfrac = fogheightpixel.a;\n"
1151 " return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1153 "# ifdef USEFOGOUTSIDE\n"
1154 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1156 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1158 " return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1163 "#ifdef USEOFFSETMAPPING\n"
1164 "uniform mediump float OffsetMapping_Scale;\n"
1165 "vec2 OffsetMapping(vec2 TexCoord)\n"
1167 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1168 " // 14 sample relief mapping: linear search and then binary search\n"
1169 " // this basically steps forward a small amount repeatedly until it finds\n"
1170 " // itself inside solid, then jitters forward and back using decreasing\n"
1171 " // amounts to find the impact\n"
1172 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1173 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1174 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1175 " vec3 RT = vec3(TexCoord, 1);\n"
1176 " OffsetVector *= 0.1;\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);\n"
1184 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1185 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1186 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
1187 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
1188 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
1189 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
1190 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1193 " // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1194 " // this basically moves forward the full distance, and then backs up based\n"
1195 " // on height of samples\n"
1196 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1197 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1198 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1199 " TexCoord += OffsetVector;\n"
1200 " OffsetVector *= 0.5;\n"
1201 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1202 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1203 " return TexCoord;\n"
1206 "#endif // USEOFFSETMAPPING\n"
1208 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1209 "uniform sampler2D Texture_Attenuation;\n"
1210 "uniform samplerCube Texture_Cube;\n"
1213 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1215 "#ifdef USESHADOWMAP2D\n"
1216 "# ifdef USESHADOWSAMPLER\n"
1217 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1219 "uniform sampler2D Texture_ShadowMap2D;\n"
1223 "#ifdef USESHADOWMAPVSDCT\n"
1224 "uniform samplerCube Texture_CubeProjection;\n"
1227 "#if defined(USESHADOWMAP2D)\n"
1228 "uniform mediump vec2 ShadowMap_TextureScale;\n"
1229 "uniform mediump vec4 ShadowMap_Parameters;\n"
1232 "#if defined(USESHADOWMAP2D)\n"
1233 "# ifdef USESHADOWMAPORTHO\n"
1234 "# define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1236 "# ifdef USESHADOWMAPVSDCT\n"
1237 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1239 " vec3 adir = abs(dir);\n"
1240 " vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1241 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1242 " return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1245 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1247 " vec3 adir = abs(dir);\n"
1248 " float ma = adir.z;\n"
1249 " vec4 proj = vec4(dir, 2.5);\n"
1250 " if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1251 " if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1252 " vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1253 " 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"
1257 "#endif // defined(USESHADOWMAP2D)\n"
1259 "# ifdef USESHADOWMAP2D\n"
1260 "float ShadowMapCompare(vec3 dir)\n"
1262 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1265 "# ifdef USESHADOWSAMPLER\n"
1266 "# ifdef USESHADOWMAPPCF\n"
1267 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1268 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1269 " 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"
1271 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1274 "# ifdef USESHADOWMAPPCF\n"
1275 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1276 "# ifdef GL_ARB_texture_gather\n"
1277 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1279 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1281 " vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1282 "# if USESHADOWMAPPCF > 1\n"
1283 " vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1284 " vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1285 " vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1286 " vec4 group4 = step(shadowmaptc.z, texval(-2.0, 0.0));\n"
1287 " vec4 group5 = step(shadowmaptc.z, texval( 0.0, 0.0));\n"
1288 " vec4 group6 = step(shadowmaptc.z, texval( 2.0, 0.0));\n"
1289 " vec4 group7 = step(shadowmaptc.z, texval(-2.0, 2.0));\n"
1290 " vec4 group8 = step(shadowmaptc.z, texval( 0.0, 2.0));\n"
1291 " vec4 group9 = step(shadowmaptc.z, texval( 2.0, 2.0));\n"
1292 " vec4 locols = vec4(group1.ab, group3.ab);\n"
1293 " vec4 hicols = vec4(group7.rg, group9.rg);\n"
1294 " locols.yz += group2.ab;\n"
1295 " hicols.yz += group8.rg;\n"
1296 " vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1297 " vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1298 " mix(locols, hicols, offset.y);\n"
1299 " vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1300 " cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1301 " f = dot(cols, vec4(1.0/25.0));\n"
1303 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1304 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1305 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1306 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1307 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1308 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1309 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1312 "# ifdef GL_EXT_gpu_shader4\n"
1313 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1315 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1317 "# if USESHADOWMAPPCF > 1\n"
1318 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1319 " center *= ShadowMap_TextureScale;\n"
1320 " 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"
1321 " 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"
1322 " 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"
1323 " 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"
1324 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1325 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1327 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1328 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1329 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1330 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1331 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1332 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1336 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1339 "# ifdef USESHADOWMAPORTHO\n"
1340 " return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1346 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1347 "#endif // FRAGMENT_SHADER\n"
1352 "#ifdef MODE_DEFERREDGEOMETRY\n"
1353 "#ifdef VERTEX_SHADER\n"
1354 "uniform highp mat4 TexMatrix;\n"
1355 "#ifdef USEVERTEXTEXTUREBLEND\n"
1356 "uniform highp mat4 BackgroundTexMatrix;\n"
1358 "uniform highp mat4 ModelViewMatrix;\n"
1361 " TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
1362 "#ifdef USEVERTEXTEXTUREBLEND\n"
1363 " VertexColor = Attrib_Color;\n"
1364 " TexCoord2 = vec2(BackgroundTexMatrix * Attrib_TexCoord0);\n"
1367 " // transform unnormalized eye direction into tangent space\n"
1368 "#ifdef USEOFFSETMAPPING\n"
1369 " vec3 EyeVectorModelSpace = EyePosition - Attrib_Position.xyz;\n"
1370 " EyeVector.x = dot(EyeVectorModelSpace, Attrib_TexCoord1.xyz);\n"
1371 " EyeVector.y = dot(EyeVectorModelSpace, Attrib_TexCoord2.xyz);\n"
1372 " EyeVector.z = dot(EyeVectorModelSpace, Attrib_TexCoord3.xyz);\n"
1375 " VectorS = (ModelViewMatrix * vec4(Attrib_TexCoord1.xyz, 0)).xyz;\n"
1376 " VectorT = (ModelViewMatrix * vec4(Attrib_TexCoord2.xyz, 0)).xyz;\n"
1377 " VectorR = (ModelViewMatrix * vec4(Attrib_TexCoord3.xyz, 0)).xyz;\n"
1378 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1380 "#endif // VERTEX_SHADER\n"
1382 "#ifdef FRAGMENT_SHADER\n"
1385 "#ifdef USEOFFSETMAPPING\n"
1386 " // apply offsetmapping\n"
1387 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1388 "#define TexCoord TexCoordOffset\n"
1391 "#ifdef USEALPHAKILL\n"
1392 " if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1396 "#ifdef USEVERTEXTEXTUREBLEND\n"
1397 " float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1398 " float terrainblend = clamp(float(VertexColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1399 " //float terrainblend = min(float(VertexColor.a) * alpha * 2.0, float(1.0));\n"
1400 " //float terrainblend = float(VertexColor.a) * alpha > 0.5;\n"
1403 "#ifdef USEVERTEXTEXTUREBLEND\n"
1404 " vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1405 " float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1407 " vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1408 " float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1411 " gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1413 "#endif // FRAGMENT_SHADER\n"
1414 "#else // !MODE_DEFERREDGEOMETRY\n"
1419 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1420 "#ifdef VERTEX_SHADER\n"
1421 "uniform highp mat4 ModelViewMatrix;\n"
1424 " ModelViewPosition = ModelViewMatrix * Attrib_Position;\n"
1425 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1427 "#endif // VERTEX_SHADER\n"
1429 "#ifdef FRAGMENT_SHADER\n"
1430 "uniform highp mat4 ViewToLight;\n"
1431 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1432 "uniform highp vec2 ScreenToDepth;\n"
1433 "uniform myhalf3 DeferredColor_Ambient;\n"
1434 "uniform myhalf3 DeferredColor_Diffuse;\n"
1435 "#ifdef USESPECULAR\n"
1436 "uniform myhalf3 DeferredColor_Specular;\n"
1437 "uniform myhalf SpecularPower;\n"
1439 "uniform myhalf2 PixelToScreenTexCoord;\n"
1442 " // calculate viewspace pixel position\n"
1443 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1445 " position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1446 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1447 " // decode viewspace pixel normal\n"
1448 " myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1449 " myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1450 " // surfacenormal = pixel normal in viewspace\n"
1451 " // LightVector = pixel to light in viewspace\n"
1452 " // CubeVector = position in lightspace\n"
1453 " // eyevector = pixel to view in viewspace\n"
1454 " vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1455 " myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1456 "#ifdef USEDIFFUSE\n"
1457 " // calculate diffuse shading\n"
1458 " myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1459 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1461 "#ifdef USESPECULAR\n"
1462 " // calculate directional shading\n"
1463 " vec3 eyevector = position * -1.0;\n"
1464 "# ifdef USEEXACTSPECULARMATH\n"
1465 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1467 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1468 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1472 "#if defined(USESHADOWMAP2D)\n"
1473 " fade *= ShadowMapCompare(CubeVector);\n"
1476 "#ifdef USEDIFFUSE\n"
1477 " gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1479 " gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1481 "#ifdef USESPECULAR\n"
1482 " gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1484 " gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1487 "# ifdef USECUBEFILTER\n"
1488 " vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1489 " gl_FragData[0].rgb *= cubecolor;\n"
1490 " gl_FragData[1].rgb *= cubecolor;\n"
1493 "#endif // FRAGMENT_SHADER\n"
1494 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1499 "#ifdef MODE_DEFERREDBOUNCELIGHT\n"
1500 "#ifdef VERTEX_SHADER\n"
1501 "uniform highp mat4 ModelViewMatrix;\n"
1504 " ModelViewPosition = ModelViewMatrix * Attrib_Position;\n"
1505 " LightOriginInvRadius.xyz = (ModelViewMatrix * vec4(Attrib_TexCoord0.xyz, 1.0)).xyz;\n"
1506 " LightOriginInvRadius.w = Attrib_TexCoord0.w;\n"
1507 " LightColor = Attrib_Color;\n"
1508 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1510 "#endif // VERTEX_SHADER\n"
1512 "#ifdef FRAGMENT_SHADER\n"
1513 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1514 "uniform highp vec2 ScreenToDepth;\n"
1515 "uniform myhalf2 PixelToScreenTexCoord;\n"
1518 " // calculate viewspace pixel position\n"
1519 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1521 " position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1522 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1523 " vec3 CubeVector = (position - LightOriginInvRadius.xyz) * LightOriginInvRadius.w;\n"
1524 " gl_FragData[0] = vec4(LightColor.rgb * max(0.0, 1.0 - length(CubeVector)), 1.0);\n"
1526 "#endif // FRAGMENT_SHADER\n"
1527 "#else // !MODE_DEFERREDBOUNCELIGHT\n"
1532 "#ifdef VERTEX_SHADER\n"
1533 "uniform highp mat4 TexMatrix;\n"
1534 "#ifdef USEVERTEXTEXTUREBLEND\n"
1535 "uniform highp mat4 BackgroundTexMatrix;\n"
1537 "#ifdef MODE_LIGHTSOURCE\n"
1538 "uniform highp mat4 ModelToLight;\n"
1540 "#ifdef USESHADOWMAPORTHO\n"
1541 "uniform highp mat4 ShadowMapMatrix;\n"
1545 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1546 " VertexColor = Attrib_Color;\n"
1548 " // copy the surface texcoord\n"
1549 " TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
1550 "#ifdef USEVERTEXTEXTUREBLEND\n"
1551 " TexCoord2 = vec2(BackgroundTexMatrix * Attrib_TexCoord0);\n"
1553 "#ifdef USELIGHTMAP\n"
1554 " TexCoordLightmap = vec2(Attrib_TexCoord4);\n"
1557 "#ifdef MODE_LIGHTSOURCE\n"
1558 " // transform vertex position into light attenuation/cubemap space\n"
1559 " // (-1 to +1 across the light box)\n"
1560 " CubeVector = vec3(ModelToLight * Attrib_Position);\n"
1562 "# ifdef USEDIFFUSE\n"
1563 " // transform unnormalized light direction into tangent space\n"
1564 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
1565 " // normalize it per pixel)\n"
1566 " vec3 lightminusvertex = LightPosition - Attrib_Position.xyz;\n"
1567 " LightVector.x = dot(lightminusvertex, Attrib_TexCoord1.xyz);\n"
1568 " LightVector.y = dot(lightminusvertex, Attrib_TexCoord2.xyz);\n"
1569 " LightVector.z = dot(lightminusvertex, Attrib_TexCoord3.xyz);\n"
1573 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1574 " LightVector.x = dot(LightDir, Attrib_TexCoord1.xyz);\n"
1575 " LightVector.y = dot(LightDir, Attrib_TexCoord2.xyz);\n"
1576 " LightVector.z = dot(LightDir, Attrib_TexCoord3.xyz);\n"
1579 " // transform unnormalized eye direction into tangent space\n"
1580 "#ifdef USEEYEVECTOR\n"
1581 " vec3 EyeVectorModelSpace = EyePosition - Attrib_Position.xyz;\n"
1582 " EyeVector.x = dot(EyeVectorModelSpace, Attrib_TexCoord1.xyz);\n"
1583 " EyeVector.y = dot(EyeVectorModelSpace, Attrib_TexCoord2.xyz);\n"
1584 " EyeVector.z = dot(EyeVectorModelSpace, Attrib_TexCoord3.xyz);\n"
1588 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - Attrib_Position.xyz;\n"
1589 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, Attrib_Position);\n"
1592 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1593 " VectorS = Attrib_TexCoord1.xyz;\n"
1594 " VectorT = Attrib_TexCoord2.xyz;\n"
1595 " VectorR = Attrib_TexCoord3.xyz;\n"
1598 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1599 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1601 "#ifdef USESHADOWMAPORTHO\n"
1602 " ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1605 "#ifdef USEREFLECTION\n"
1606 " ModelViewProjectionPosition = gl_Position;\n"
1609 "#endif // VERTEX_SHADER\n"
1614 "#ifdef FRAGMENT_SHADER\n"
1615 "#ifdef USEDEFERREDLIGHTMAP\n"
1616 "uniform myhalf2 PixelToScreenTexCoord;\n"
1617 "uniform myhalf3 DeferredMod_Diffuse;\n"
1618 "uniform myhalf3 DeferredMod_Specular;\n"
1620 "uniform myhalf3 Color_Ambient;\n"
1621 "uniform myhalf3 Color_Diffuse;\n"
1622 "uniform myhalf3 Color_Specular;\n"
1623 "uniform myhalf SpecularPower;\n"
1625 "uniform myhalf3 Color_Glow;\n"
1627 "uniform myhalf Alpha;\n"
1628 "#ifdef USEREFLECTION\n"
1629 "uniform mediump vec4 DistortScaleRefractReflect;\n"
1630 "uniform mediump vec4 ScreenScaleRefractReflect;\n"
1631 "uniform mediump vec4 ScreenCenterRefractReflect;\n"
1632 "uniform lowp vec4 ReflectColor;\n"
1634 "#ifdef USEREFLECTCUBE\n"
1635 "uniform highp mat4 ModelToReflectCube;\n"
1636 "uniform sampler2D Texture_ReflectMask;\n"
1637 "uniform samplerCube Texture_ReflectCube;\n"
1639 "#ifdef MODE_LIGHTDIRECTION\n"
1640 "uniform myhalf3 LightColor;\n"
1642 "#ifdef MODE_LIGHTSOURCE\n"
1643 "uniform myhalf3 LightColor;\n"
1647 "#ifdef USEOFFSETMAPPING\n"
1648 " // apply offsetmapping\n"
1649 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1650 "#define TexCoord TexCoordOffset\n"
1653 " // combine the diffuse textures (base, pants, shirt)\n"
1654 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1655 "#ifdef USEALPHAKILL\n"
1656 " if (color.a < 0.5)\n"
1659 " color.a *= Alpha;\n"
1660 "#ifdef USECOLORMAPPING\n"
1661 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1663 "#ifdef USEVERTEXTEXTUREBLEND\n"
1664 " myhalf terrainblend = clamp(myhalf(VertexColor.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1665 " //myhalf terrainblend = min(myhalf(VertexColor.a) * color.a * 2.0, myhalf(1.0));\n"
1666 " //myhalf terrainblend = myhalf(VertexColor.a) * color.a > 0.5;\n"
1667 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1669 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1672 " // get the surface normal\n"
1673 "#ifdef USEVERTEXTEXTUREBLEND\n"
1674 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1676 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1679 " // get the material colors\n"
1680 " myhalf3 diffusetex = color.rgb;\n"
1681 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1682 "# ifdef USEVERTEXTEXTUREBLEND\n"
1683 " myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1685 " myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1689 "#ifdef USEREFLECTCUBE\n"
1690 " vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1691 " vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1692 " vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1693 " diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1699 "#ifdef MODE_LIGHTSOURCE\n"
1700 " // light source\n"
1701 "#ifdef USEDIFFUSE\n"
1702 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1703 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1704 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1705 "#ifdef USESPECULAR\n"
1706 "#ifdef USEEXACTSPECULARMATH\n"
1707 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1709 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1710 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1712 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1715 " color.rgb = diffusetex * Color_Ambient;\n"
1717 " color.rgb *= LightColor;\n"
1718 " color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1719 "#if defined(USESHADOWMAP2D)\n"
1720 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1722 "# ifdef USECUBEFILTER\n"
1723 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1725 "#endif // MODE_LIGHTSOURCE\n"
1730 "#ifdef MODE_LIGHTDIRECTION\n"
1732 "#ifdef USEDIFFUSE\n"
1733 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1735 "#define lightcolor LightColor\n"
1736 "#endif // MODE_LIGHTDIRECTION\n"
1737 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1739 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1740 " myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1741 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1742 " // convert modelspace light vector to tangentspace\n"
1743 " myhalf3 lightnormal;\n"
1744 " lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1745 " lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1746 " lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1747 " lightnormal = normalize(lightnormal); // VectorS/T/R are not always perfectly normalized, and EXACTSPECULARMATH is very picky about this\n"
1748 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1749 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1750 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1751 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1752 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1753 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1754 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1755 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1756 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1757 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1758 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1759 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1761 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1762 " myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1763 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1769 "#ifdef MODE_FAKELIGHT\n"
1771 "myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
1772 "myhalf3 lightcolor = myhalf3(1.0);\n"
1773 "#endif // MODE_FAKELIGHT\n"
1778 "#ifdef MODE_LIGHTMAP\n"
1779 " color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1780 "#endif // MODE_LIGHTMAP\n"
1781 "#ifdef MODE_VERTEXCOLOR\n"
1782 " color.rgb = diffusetex * (Color_Ambient + myhalf3(VertexColor.rgb) * Color_Diffuse);\n"
1783 "#endif // MODE_VERTEXCOLOR\n"
1784 "#ifdef MODE_FLATCOLOR\n"
1785 " color.rgb = diffusetex * Color_Ambient;\n"
1786 "#endif // MODE_FLATCOLOR\n"
1792 "# ifdef USEDIFFUSE\n"
1793 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1794 "# ifdef USESPECULAR\n"
1795 "# ifdef USEEXACTSPECULARMATH\n"
1796 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1798 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1799 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1801 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1803 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1806 " color.rgb = diffusetex * Color_Ambient;\n"
1810 "#ifdef USESHADOWMAPORTHO\n"
1811 " color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1814 "#ifdef USEDEFERREDLIGHTMAP\n"
1815 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1816 " color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1817 " color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1821 "#ifdef USEVERTEXTEXTUREBLEND\n"
1822 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1824 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1829 " color.rgb = FogVertex(color.rgb);\n"
1832 " // 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"
1833 "#ifdef USEREFLECTION\n"
1834 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1835 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1836 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1837 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1838 " // FIXME temporary hack to detect the case that the reflection\n"
1839 " // gets blackened at edges due to leaving the area that contains actual\n"
1841 " // Remove this 'ack once we have a better way to stop this thing from\n"
1843 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1844 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1845 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1846 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1847 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1848 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1851 " gl_FragColor = vec4(color);\n"
1853 "#endif // FRAGMENT_SHADER\n"
1855 "#endif // !MODE_DEFERREDBOUNCELIGHT\n"
1856 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1857 "#endif // !MODE_DEFERREDGEOMETRY\n"
1858 "#endif // !MODE_WATER\n"
1859 "#endif // !MODE_REFRACTION\n"
1860 "#endif // !MODE_BLOOMBLUR\n"
1861 "#endif // !MODE_GENERIC\n"
1862 "#endif // !MODE_POSTPROCESS\n"
1863 "#endif // !MODE_SHOWDEPTH\n"
1864 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1868 =========================================================================================================================================================
1872 =========================================================================================================================================================
1876 =========================================================================================================================================================
1880 =========================================================================================================================================================
1884 =========================================================================================================================================================
1888 =========================================================================================================================================================
1892 =========================================================================================================================================================
1895 const char *builtinhlslshaderstring =
1896 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1897 "// written by Forest 'LordHavoc' Hale\n"
1898 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1900 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1901 "#if defined(USEREFLECTION)\n"
1902 "#undef USESHADOWMAPORTHO\n"
1905 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1908 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1909 "#define USELIGHTMAP\n"
1911 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
1912 "#define USEEYEVECTOR\n"
1915 "#ifdef FRAGMENT_SHADER\n"
1917 "//#undef USESHADOWMAPPCF\n"
1918 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1919 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1921 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1925 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1926 "#ifdef VERTEX_SHADER\n"
1929 "float4 gl_Vertex : POSITION,\n"
1930 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1931 "out float4 gl_Position : POSITION,\n"
1932 "out float Depth : TEXCOORD0\n"
1935 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1936 " Depth = gl_Position.z;\n"
1940 "#ifdef FRAGMENT_SHADER\n"
1943 "float Depth : TEXCOORD0,\n"
1944 "out float4 gl_FragColor : COLOR\n"
1947 "// float4 temp = float4(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0),0.0);\n"
1948 " float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
1949 " temp.yz -= floor(temp.yz);\n"
1950 " gl_FragColor = temp;\n"
1951 "// gl_FragColor = float4(Depth,0,0,0);\n"
1954 "#else // !MODE_DEPTH_ORSHADOW\n"
1959 "#ifdef MODE_SHOWDEPTH\n"
1960 "#ifdef VERTEX_SHADER\n"
1963 "float4 gl_Vertex : POSITION,\n"
1964 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1965 "out float4 gl_Position : POSITION,\n"
1966 "out float4 gl_FrontColor : COLOR0\n"
1969 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1970 " gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1974 "#ifdef FRAGMENT_SHADER\n"
1977 "float4 gl_FrontColor : COLOR0,\n"
1978 "out float4 gl_FragColor : COLOR\n"
1981 " gl_FragColor = gl_FrontColor;\n"
1984 "#else // !MODE_SHOWDEPTH\n"
1989 "#ifdef MODE_POSTPROCESS\n"
1991 "#ifdef VERTEX_SHADER\n"
1994 "float4 gl_Vertex : POSITION,\n"
1995 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1996 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1997 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1998 "out float4 gl_Position : POSITION,\n"
1999 "out float2 TexCoord1 : TEXCOORD0,\n"
2000 "out float2 TexCoord2 : TEXCOORD1\n"
2003 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2004 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
2006 " TexCoord2 = gl_MultiTexCoord4.xy;\n"
2011 "#ifdef FRAGMENT_SHADER\n"
2014 "float2 TexCoord1 : TEXCOORD0,\n"
2015 "float2 TexCoord2 : TEXCOORD1,\n"
2016 "uniform sampler Texture_First : register(s0),\n"
2018 "uniform sampler Texture_Second : register(s1),\n"
2020 "#ifdef USEGAMMARAMPS\n"
2021 "uniform sampler Texture_GammaRamps : register(s2),\n"
2023 "#ifdef USESATURATION\n"
2024 "uniform float Saturation : register(c30),\n"
2026 "#ifdef USEVIEWTINT\n"
2027 "uniform float4 ViewTintColor : register(c41),\n"
2029 "uniform float4 UserVec1 : register(c37),\n"
2030 "uniform float4 UserVec2 : register(c38),\n"
2031 "uniform float4 UserVec3 : register(c39),\n"
2032 "uniform float4 UserVec4 : register(c40),\n"
2033 "uniform float ClientTime : register(c2),\n"
2034 "uniform float2 PixelSize : register(c25),\n"
2035 "uniform float4 BloomColorSubtract : register(c43),\n"
2036 "out float4 gl_FragColor : COLOR\n"
2039 " gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
2041 " gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
2043 "#ifdef USEVIEWTINT\n"
2044 " gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
2047 "#ifdef USEPOSTPROCESSING\n"
2048 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
2049 "// 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"
2050 " float sobel = 1.0;\n"
2051 " // float2 ts = textureSize(Texture_First, 0);\n"
2052 " // float2 px = float2(1/ts.x, 1/ts.y);\n"
2053 " float2 px = PixelSize;\n"
2054 " float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2055 " float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x, 0.0)).rgb;\n"
2056 " float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2057 " float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2058 " float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x, 0.0)).rgb;\n"
2059 " float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2060 " float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2061 " float3 y2 = tex2D(Texture_First, TexCoord1 + float2( 0.0,-px.y)).rgb;\n"
2062 " float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2063 " float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2064 " float3 y5 = tex2D(Texture_First, TexCoord1 + float2( 0.0, px.y)).rgb;\n"
2065 " float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2066 " float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
2067 " float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
2068 " float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
2069 " float px4 = 1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
2070 " float px5 = 2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
2071 " float px6 = 1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
2072 " float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
2073 " float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
2074 " float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
2075 " float py4 = 1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
2076 " float py5 = 2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
2077 " float py6 = 1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
2078 " sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
2079 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2080 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2081 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2082 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107, 0.707107)) * UserVec1.y;\n"
2083 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990, 0.891007)) * UserVec1.y;\n"
2084 " gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2085 " gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2088 "#ifdef USESATURATION\n"
2089 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2090 " float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2091 " // 'vampire sight' effect, wheres red is compensated\n"
2092 " #ifdef SATURATION_REDCOMPENSATE\n"
2093 " float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
2094 " gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2095 " gl_FragColor.r += r;\n"
2097 " // normal desaturation\n"
2098 " //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2099 " gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2103 "#ifdef USEGAMMARAMPS\n"
2104 " gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2105 " gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2106 " gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2110 "#else // !MODE_POSTPROCESS\n"
2115 "#ifdef MODE_GENERIC\n"
2116 "#ifdef VERTEX_SHADER\n"
2119 "float4 gl_Vertex : POSITION,\n"
2120 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2121 "float4 gl_Color : COLOR0,\n"
2122 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2123 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2124 "out float4 gl_Position : POSITION,\n"
2125 "#ifdef USEDIFFUSE\n"
2126 "out float2 TexCoord1 : TEXCOORD0,\n"
2128 "#ifdef USESPECULAR\n"
2129 "out float2 TexCoord2 : TEXCOORD1,\n"
2131 "out float4 gl_FrontColor : COLOR\n"
2135 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2137 " gl_FrontColor = gl_Color; // Cg is forward\n"
2139 "#ifdef USEDIFFUSE\n"
2140 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
2142 "#ifdef USESPECULAR\n"
2143 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
2145 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2149 "#ifdef FRAGMENT_SHADER\n"
2153 "float4 gl_FrontColor : COLOR0,\n"
2154 "float2 TexCoord1 : TEXCOORD0,\n"
2155 "float2 TexCoord2 : TEXCOORD1,\n"
2156 "#ifdef USEDIFFUSE\n"
2157 "uniform sampler Texture_First : register(s0),\n"
2159 "#ifdef USESPECULAR\n"
2160 "uniform sampler Texture_Second : register(s1),\n"
2162 "out float4 gl_FragColor : COLOR\n"
2165 "#ifdef USEVIEWTINT\n"
2166 " gl_FragColor = gl_FrontColor;\n"
2168 " gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
2170 "#ifdef USEDIFFUSE\n"
2171 " gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2174 "#ifdef USESPECULAR\n"
2175 " float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2176 "# ifdef USECOLORMAPPING\n"
2177 " gl_FragColor *= tex2;\n"
2180 " gl_FragColor += tex2;\n"
2182 "# ifdef USEVERTEXTEXTUREBLEND\n"
2183 " gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2188 "#else // !MODE_GENERIC\n"
2193 "#ifdef MODE_BLOOMBLUR\n"
2194 "#ifdef VERTEX_SHADER\n"
2197 "float4 gl_Vertex : POSITION,\n"
2198 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2199 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2200 "out float4 gl_Position : POSITION,\n"
2201 "out float2 TexCoord : TEXCOORD0\n"
2204 " TexCoord = gl_MultiTexCoord0.xy;\n"
2205 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2209 "#ifdef FRAGMENT_SHADER\n"
2213 "float2 TexCoord : TEXCOORD0,\n"
2214 "uniform sampler Texture_First : register(s0),\n"
2215 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2216 "out float4 gl_FragColor : COLOR\n"
2220 " float2 tc = TexCoord;\n"
2221 " float3 color = tex2D(Texture_First, tc).rgb;\n"
2222 " tc += BloomBlur_Parameters.xy;\n"
2223 " for (i = 1;i < SAMPLES;i++)\n"
2225 " color += tex2D(Texture_First, tc).rgb;\n"
2226 " tc += BloomBlur_Parameters.xy;\n"
2228 " gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2231 "#else // !MODE_BLOOMBLUR\n"
2232 "#ifdef MODE_REFRACTION\n"
2233 "#ifdef VERTEX_SHADER\n"
2236 "float4 gl_Vertex : POSITION,\n"
2237 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2238 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2239 "uniform float4x4 TexMatrix : register(c0),\n"
2240 "uniform float3 EyePosition : register(c24),\n"
2241 "out float4 gl_Position : POSITION,\n"
2242 "out float2 TexCoord : TEXCOORD0,\n"
2243 "out float3 EyeVector : TEXCOORD1,\n"
2244 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2247 " TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2248 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2249 " ModelViewProjectionPosition = gl_Position;\n"
2253 "#ifdef FRAGMENT_SHADER\n"
2256 "float2 TexCoord : TEXCOORD0,\n"
2257 "float3 EyeVector : TEXCOORD1,\n"
2258 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2259 "uniform sampler Texture_Normal : register(s0),\n"
2260 "uniform sampler Texture_Refraction : register(s3),\n"
2261 "uniform sampler Texture_Reflection : register(s7),\n"
2262 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2263 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2264 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2265 "uniform float4 RefractColor : register(c29),\n"
2266 "out float4 gl_FragColor : COLOR\n"
2269 " float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2270 " //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"
2271 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2272 " float2 ScreenTexCoord = SafeScreenTexCoord + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy;\n"
2273 " // FIXME temporary hack to detect the case that the reflection\n"
2274 " // gets blackened at edges due to leaving the area that contains actual\n"
2276 " // Remove this 'ack once we have a better way to stop this thing from\n"
2278 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2279 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2280 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2281 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2282 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2283 " gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
2286 "#else // !MODE_REFRACTION\n"
2291 "#ifdef MODE_WATER\n"
2292 "#ifdef VERTEX_SHADER\n"
2296 "float4 gl_Vertex : POSITION,\n"
2297 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2298 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2299 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2300 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2301 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2302 "uniform float4x4 TexMatrix : register(c0),\n"
2303 "uniform float3 EyePosition : register(c24),\n"
2304 "out float4 gl_Position : POSITION,\n"
2305 "out float2 TexCoord : TEXCOORD0,\n"
2306 "out float3 EyeVector : TEXCOORD1,\n"
2307 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2310 " TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2311 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2312 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2313 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2314 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2315 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2316 " ModelViewProjectionPosition = gl_Position;\n"
2320 "#ifdef FRAGMENT_SHADER\n"
2323 "float2 TexCoord : TEXCOORD0,\n"
2324 "float3 EyeVector : TEXCOORD1,\n"
2325 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2326 "uniform sampler Texture_Normal : register(s0),\n"
2327 "uniform sampler Texture_Refraction : register(s3),\n"
2328 "uniform sampler Texture_Reflection : register(s7),\n"
2329 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2330 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2331 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2332 "uniform float4 RefractColor : register(c29),\n"
2333 "uniform float4 ReflectColor : register(c26),\n"
2334 "uniform float ReflectFactor : register(c27),\n"
2335 "uniform float ReflectOffset : register(c28),\n"
2336 "out float4 gl_FragColor : COLOR\n"
2339 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2340 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2341 " float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2342 " //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2343 " float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2344 " // FIXME temporary hack to detect the case that the reflection\n"
2345 " // gets blackened at edges due to leaving the area that contains actual\n"
2347 " // Remove this 'ack once we have a better way to stop this thing from\n"
2349 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2350 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2351 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2352 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2353 " ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2354 " f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2355 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2356 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2357 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2358 " ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2359 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2360 " gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
2363 "#else // !MODE_WATER\n"
2368 "// 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"
2370 "// fragment shader specific:\n"
2371 "#ifdef FRAGMENT_SHADER\n"
2374 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2377 "#ifdef USEFOGHEIGHTTEXTURE\n"
2378 " float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2379 " fogfrac = fogheightpixel.a;\n"
2380 " return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2382 "# ifdef USEFOGOUTSIDE\n"
2383 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2385 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2387 " return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2392 "#ifdef USEOFFSETMAPPING\n"
2393 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2395 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2396 " // 14 sample relief mapping: linear search and then binary search\n"
2397 " // this basically steps forward a small amount repeatedly until it finds\n"
2398 " // itself inside solid, then jitters forward and back using decreasing\n"
2399 " // amounts to find the impact\n"
2400 " //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2401 " //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2402 " float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2403 " float3 RT = float3(TexCoord, 1);\n"
2404 " OffsetVector *= 0.1;\n"
2405 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2406 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2407 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2408 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2409 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2410 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2411 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2412 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2413 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2414 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
2415 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
2416 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
2417 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
2418 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2421 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2422 " // this basically moves forward the full distance, and then backs up based\n"
2423 " // on height of samples\n"
2424 " //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2425 " //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2426 " float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2427 " TexCoord += OffsetVector;\n"
2428 " OffsetVector *= 0.333;\n"
2429 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2430 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2431 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2432 " return TexCoord;\n"
2435 "#endif // USEOFFSETMAPPING\n"
2437 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2438 "#if defined(USESHADOWMAP2D)\n"
2439 "# ifdef USESHADOWMAPORTHO\n"
2440 "# define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2442 "# ifdef USESHADOWMAPVSDCT\n"
2443 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2445 " float3 adir = abs(dir);\n"
2446 " float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2447 " float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2448 " return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2451 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2453 " float3 adir = abs(dir);\n"
2454 " float ma = adir.z;\n"
2455 " float4 proj = float4(dir, 2.5);\n"
2456 " if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2457 " if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2459 " 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"
2461 " float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2462 " 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"
2467 "#endif // defined(USESHADOWMAP2D)\n"
2469 "# ifdef USESHADOWMAP2D\n"
2470 "#ifdef USESHADOWMAPVSDCT\n"
2471 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2473 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2476 "#ifdef USESHADOWMAPVSDCT\n"
2477 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2479 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2483 "# ifdef USESHADOWSAMPLER\n"
2484 "# ifdef USESHADOWMAPPCF\n"
2485 "# define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r \n"
2486 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2487 " 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"
2489 " f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2492 "# ifdef USESHADOWMAPPCF\n"
2493 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2494 "# ifdef GL_ARB_texture_gather\n"
2495 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2497 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2499 " float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2500 "# if USESHADOWMAPPCF > 1\n"
2501 " float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2502 " float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2503 " float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2504 " float4 group4 = step(shadowmaptc.z, texval(-2.0, 0.0));\n"
2505 " float4 group5 = step(shadowmaptc.z, texval( 0.0, 0.0));\n"
2506 " float4 group6 = step(shadowmaptc.z, texval( 2.0, 0.0));\n"
2507 " float4 group7 = step(shadowmaptc.z, texval(-2.0, 2.0));\n"
2508 " float4 group8 = step(shadowmaptc.z, texval( 0.0, 2.0));\n"
2509 " float4 group9 = step(shadowmaptc.z, texval( 2.0, 2.0));\n"
2510 " float4 locols = float4(group1.ab, group3.ab);\n"
2511 " float4 hicols = float4(group7.rg, group9.rg);\n"
2512 " locols.yz += group2.ab;\n"
2513 " hicols.yz += group8.rg;\n"
2514 " float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2515 " float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2516 " lerp(locols, hicols, offset.y);\n"
2517 " float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2518 " cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2519 " f = dot(cols, float4(1.0/25.0));\n"
2521 " float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2522 " float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2523 " float4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
2524 " float4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
2525 " float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2526 " lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2527 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2530 "# ifdef GL_EXT_gpu_shader4\n"
2531 "# define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2533 "# define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r \n"
2535 "# if USESHADOWMAPPCF > 1\n"
2536 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2537 " center *= ShadowMap_TextureScale;\n"
2538 " 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"
2539 " 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"
2540 " 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"
2541 " 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"
2542 " float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2543 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2545 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2546 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2547 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2548 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2549 " float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2550 " f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2554 " f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2557 "# ifdef USESHADOWMAPORTHO\n"
2558 " return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2564 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2565 "#endif // FRAGMENT_SHADER\n"
2570 "#ifdef MODE_DEFERREDGEOMETRY\n"
2571 "#ifdef VERTEX_SHADER\n"
2574 "float4 gl_Vertex : POSITION,\n"
2575 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2576 "#ifdef USEVERTEXTEXTUREBLEND\n"
2577 "float4 gl_Color : COLOR0,\n"
2579 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2580 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2581 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2582 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2583 "uniform float4x4 TexMatrix : register(c0),\n"
2584 "#ifdef USEVERTEXTEXTUREBLEND\n"
2585 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2587 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2588 "#ifdef USEOFFSETMAPPING\n"
2589 "uniform float3 EyePosition : register(c24),\n"
2591 "out float4 gl_Position : POSITION,\n"
2592 "#ifdef USEVERTEXTEXTUREBLEND\n"
2593 "out float4 gl_FrontColor : COLOR,\n"
2595 "out float4 TexCoordBoth : TEXCOORD0,\n"
2596 "#ifdef USEOFFSETMAPPING\n"
2597 "out float3 EyeVector : TEXCOORD2,\n"
2599 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2600 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2601 "out float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\n"
2604 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2605 "#ifdef USEVERTEXTEXTUREBLEND\n"
2607 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2609 " gl_FrontColor = gl_Color; // Cg is forward\n"
2611 " TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2614 " // transform unnormalized eye direction into tangent space\n"
2615 "#ifdef USEOFFSETMAPPING\n"
2616 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2617 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2618 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2619 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2622 " VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2623 " VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2624 " VectorR.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2625 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2626 " VectorR.w = gl_Position.z;\n"
2628 "#endif // VERTEX_SHADER\n"
2630 "#ifdef FRAGMENT_SHADER\n"
2633 "float4 TexCoordBoth : TEXCOORD0,\n"
2634 "float3 EyeVector : TEXCOORD2,\n"
2635 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2636 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2637 "float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
2638 "uniform sampler Texture_Normal : register(s0),\n"
2639 "#ifdef USEALPHAKILL\n"
2640 "uniform sampler Texture_Color : register(s1),\n"
2642 "uniform sampler Texture_Gloss : register(s2),\n"
2643 "#ifdef USEVERTEXTEXTUREBLEND\n"
2644 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2645 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2647 "#ifdef USEOFFSETMAPPING\n"
2648 "uniform float OffsetMapping_Scale : register(c24),\n"
2650 "uniform half SpecularPower : register(c36),\n"
2652 "out float4 gl_FragData0 : COLOR0,\n"
2653 "out float4 gl_FragData1 : COLOR1\n"
2655 "out float4 gl_FragColor : COLOR\n"
2659 " float2 TexCoord = TexCoordBoth.xy;\n"
2660 "#ifdef USEOFFSETMAPPING\n"
2661 " // apply offsetmapping\n"
2662 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2663 "#define TexCoord TexCoordOffset\n"
2666 "#ifdef USEALPHAKILL\n"
2667 " if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2671 "#ifdef USEVERTEXTEXTUREBLEND\n"
2672 " float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2673 " float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2674 " //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2675 " //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2678 "#ifdef USEVERTEXTEXTUREBLEND\n"
2679 " float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2680 " float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2682 " float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2683 " float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2687 " 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"
2688 " float Depth = VectorR.w / 256.0;\n"
2689 " float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
2690 "// float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
2691 " depthcolor.yz -= floor(depthcolor.yz);\n"
2692 " gl_FragData1 = depthcolor;\n"
2694 " gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2697 "#endif // FRAGMENT_SHADER\n"
2698 "#else // !MODE_DEFERREDGEOMETRY\n"
2703 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2704 "#ifdef VERTEX_SHADER\n"
2707 "float4 gl_Vertex : POSITION,\n"
2708 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2709 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2710 "out float4 gl_Position : POSITION,\n"
2711 "out float4 ModelViewPosition : TEXCOORD0\n"
2714 " ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2715 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2717 "#endif // VERTEX_SHADER\n"
2719 "#ifdef FRAGMENT_SHADER\n"
2723 "float2 Pixel : VPOS,\n"
2725 "float2 Pixel : WPOS,\n"
2727 "float4 ModelViewPosition : TEXCOORD0,\n"
2728 "uniform float4x4 ViewToLight : register(c44),\n"
2729 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2730 "uniform float3 LightPosition : register(c23),\n"
2731 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2732 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2733 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2734 "#ifdef USESPECULAR\n"
2735 "uniform half3 DeferredColor_Specular : register(c11),\n"
2736 "uniform half SpecularPower : register(c36),\n"
2738 "uniform sampler Texture_Attenuation : register(s9),\n"
2739 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2740 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2742 "#ifdef USECUBEFILTER\n"
2743 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2746 "#ifdef USESHADOWMAP2D\n"
2747 "# ifdef USESHADOWSAMPLER\n"
2748 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2750 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2754 "#ifdef USESHADOWMAPVSDCT\n"
2755 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2758 "#if defined(USESHADOWMAP2D)\n"
2759 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2760 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2763 "out float4 gl_FragData0 : COLOR0,\n"
2764 "out float4 gl_FragData1 : COLOR1\n"
2767 " // calculate viewspace pixel position\n"
2768 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2769 " //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2770 " float3 position;\n"
2772 " position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
2774 " position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2776 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2777 " // decode viewspace pixel normal\n"
2778 " half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2779 " half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2780 " // surfacenormal = pixel normal in viewspace\n"
2781 " // LightVector = pixel to light in viewspace\n"
2782 " // CubeVector = position in lightspace\n"
2783 " // eyevector = pixel to view in viewspace\n"
2784 " float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2785 " half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2786 "#ifdef USEDIFFUSE\n"
2787 " // calculate diffuse shading\n"
2788 " half3 lightnormal = half3(normalize(LightPosition - position));\n"
2789 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2791 "#ifdef USESPECULAR\n"
2792 " // calculate directional shading\n"
2793 " float3 eyevector = position * -1.0;\n"
2794 "# ifdef USEEXACTSPECULARMATH\n"
2795 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
2797 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2798 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
2802 "#if defined(USESHADOWMAP2D)\n"
2803 " fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2804 "#ifdef USESHADOWMAPVSDCT\n"
2805 ", Texture_CubeProjection\n"
2810 "#ifdef USEDIFFUSE\n"
2811 " gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2813 " gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2815 "#ifdef USESPECULAR\n"
2816 " gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2818 " gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2821 "# ifdef USECUBEFILTER\n"
2822 " float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2823 " gl_FragData0.rgb *= cubecolor;\n"
2824 " gl_FragData1.rgb *= cubecolor;\n"
2827 "#endif // FRAGMENT_SHADER\n"
2828 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2833 "#ifdef VERTEX_SHADER\n"
2836 "float4 gl_Vertex : POSITION,\n"
2837 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2838 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2839 "float4 gl_Color : COLOR0,\n"
2841 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2842 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2843 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2844 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2845 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2847 "uniform float3 EyePosition : register(c24),\n"
2848 "uniform float4x4 TexMatrix : register(c0),\n"
2849 "#ifdef USEVERTEXTEXTUREBLEND\n"
2850 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2852 "#ifdef MODE_LIGHTSOURCE\n"
2853 "uniform float4x4 ModelToLight : register(c20),\n"
2855 "#ifdef MODE_LIGHTSOURCE\n"
2856 "uniform float3 LightPosition : register(c27),\n"
2858 "#ifdef MODE_LIGHTDIRECTION\n"
2859 "uniform float3 LightDir : register(c26),\n"
2861 "uniform float4 FogPlane : register(c25),\n"
2862 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2863 "uniform float3 LightPosition : register(c27),\n"
2865 "#ifdef USESHADOWMAPORTHO\n"
2866 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2868 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2869 "out float4 gl_FrontColor : COLOR,\n"
2871 "out float4 TexCoordBoth : TEXCOORD0,\n"
2872 "#ifdef USELIGHTMAP\n"
2873 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2875 "#ifdef USEEYEVECTOR\n"
2876 "out float3 EyeVector : TEXCOORD2,\n"
2878 "#ifdef USEREFLECTION\n"
2879 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2882 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2884 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE) || defined(USEDIFFUSE)\n"
2885 "out float3 LightVector : TEXCOORD1,\n"
2887 "#ifdef MODE_LIGHTSOURCE\n"
2888 "out float3 CubeVector : TEXCOORD3,\n"
2890 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2891 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2892 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2893 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2895 "#ifdef USESHADOWMAPORTHO\n"
2896 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2898 "out float4 gl_Position : POSITION\n"
2901 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2903 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2905 " gl_FrontColor = gl_Color; // Cg is forward\n"
2908 " // copy the surface texcoord\n"
2909 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2910 "#ifdef USEVERTEXTEXTUREBLEND\n"
2911 " TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2913 "#ifdef USELIGHTMAP\n"
2914 " TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2917 "#ifdef MODE_LIGHTSOURCE\n"
2918 " // transform vertex position into light attenuation/cubemap space\n"
2919 " // (-1 to +1 across the light box)\n"
2920 " CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2922 "# ifdef USEDIFFUSE\n"
2923 " // transform unnormalized light direction into tangent space\n"
2924 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
2925 " // normalize it per pixel)\n"
2926 " float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2927 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2928 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2929 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2933 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2934 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2935 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2936 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2939 " // transform unnormalized eye direction into tangent space\n"
2940 "#ifdef USEEYEVECTOR\n"
2941 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2942 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2943 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2944 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2948 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2949 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2952 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2953 " VectorS = gl_MultiTexCoord1.xyz;\n"
2954 " VectorT = gl_MultiTexCoord2.xyz;\n"
2955 " VectorR = gl_MultiTexCoord3.xyz;\n"
2958 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2959 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2961 "#ifdef USESHADOWMAPORTHO\n"
2962 " ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2965 "#ifdef USEREFLECTION\n"
2966 " ModelViewProjectionPosition = gl_Position;\n"
2969 "#endif // VERTEX_SHADER\n"
2974 "#ifdef FRAGMENT_SHADER\n"
2977 "#ifdef USEDEFERREDLIGHTMAP\n"
2979 "float2 Pixel : VPOS,\n"
2981 "float2 Pixel : WPOS,\n"
2984 "float4 gl_FrontColor : COLOR,\n"
2985 "float4 TexCoordBoth : TEXCOORD0,\n"
2986 "#ifdef USELIGHTMAP\n"
2987 "float2 TexCoordLightmap : TEXCOORD1,\n"
2989 "#ifdef USEEYEVECTOR\n"
2990 "float3 EyeVector : TEXCOORD2,\n"
2992 "#ifdef USEREFLECTION\n"
2993 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2996 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2998 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2999 "float3 LightVector : TEXCOORD1,\n"
3001 "#ifdef MODE_LIGHTSOURCE\n"
3002 "float3 CubeVector : TEXCOORD3,\n"
3004 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
3005 "float4 ModelViewPosition : TEXCOORD0,\n"
3007 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
3008 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
3009 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
3010 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
3012 "#ifdef USESHADOWMAPORTHO\n"
3013 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
3016 "uniform sampler Texture_Normal : register(s0),\n"
3017 "uniform sampler Texture_Color : register(s1),\n"
3018 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3019 "uniform sampler Texture_Gloss : register(s2),\n"
3022 "uniform sampler Texture_Glow : register(s3),\n"
3024 "#ifdef USEVERTEXTEXTUREBLEND\n"
3025 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
3026 "uniform sampler Texture_SecondaryColor : register(s5),\n"
3027 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3028 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
3031 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
3034 "#ifdef USECOLORMAPPING\n"
3035 "uniform sampler Texture_Pants : register(s4),\n"
3036 "uniform sampler Texture_Shirt : register(s7),\n"
3039 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
3040 "uniform sampler Texture_FogMask : register(s8),\n"
3042 "#ifdef USELIGHTMAP\n"
3043 "uniform sampler Texture_Lightmap : register(s9),\n"
3045 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
3046 "uniform sampler Texture_Deluxemap : register(s10),\n"
3048 "#ifdef USEREFLECTION\n"
3049 "uniform sampler Texture_Reflection : register(s7),\n"
3052 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
3053 "uniform sampler Texture_ScreenDepth : register(s13),\n"
3054 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
3056 "#ifdef USEDEFERREDLIGHTMAP\n"
3057 "uniform sampler Texture_ScreenDepth : register(s13),\n"
3058 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
3059 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
3060 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
3063 "#ifdef USECOLORMAPPING\n"
3064 "uniform half3 Color_Pants : register(c7),\n"
3065 "uniform half3 Color_Shirt : register(c8),\n"
3068 "uniform float3 FogColor : register(c16),\n"
3069 "uniform float FogRangeRecip : register(c20),\n"
3070 "uniform float FogPlaneViewDist : register(c19),\n"
3071 "uniform float FogHeightFade : register(c17),\n"
3074 "#ifdef USEOFFSETMAPPING\n"
3075 "uniform float OffsetMapping_Scale : register(c24),\n"
3078 "#ifdef USEDEFERREDLIGHTMAP\n"
3079 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
3080 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
3081 "uniform half3 DeferredMod_Specular : register(c13),\n"
3083 "uniform half3 Color_Ambient : register(c3),\n"
3084 "uniform half3 Color_Diffuse : register(c4),\n"
3085 "uniform half3 Color_Specular : register(c5),\n"
3086 "uniform half SpecularPower : register(c36),\n"
3088 "uniform half3 Color_Glow : register(c6),\n"
3090 "uniform half Alpha : register(c0),\n"
3091 "#ifdef USEREFLECTION\n"
3092 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3093 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3094 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3095 "uniform half4 ReflectColor : register(c26),\n"
3097 "#ifdef USEREFLECTCUBE\n"
3098 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3099 "uniform sampler Texture_ReflectMask : register(s5),\n"
3100 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3102 "#ifdef MODE_LIGHTDIRECTION\n"
3103 "uniform half3 LightColor : register(c21),\n"
3105 "#ifdef MODE_LIGHTSOURCE\n"
3106 "uniform half3 LightColor : register(c21),\n"
3109 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3110 "uniform sampler Texture_Attenuation : register(s9),\n"
3111 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3114 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3116 "#ifdef USESHADOWMAP2D\n"
3117 "# ifdef USESHADOWSAMPLER\n"
3118 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3120 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3124 "#ifdef USESHADOWMAPVSDCT\n"
3125 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3128 "#if defined(USESHADOWMAP2D)\n"
3129 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3130 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3132 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3134 "out float4 gl_FragColor : COLOR\n"
3137 " float2 TexCoord = TexCoordBoth.xy;\n"
3138 "#ifdef USEVERTEXTEXTUREBLEND\n"
3139 " float2 TexCoord2 = TexCoordBoth.zw;\n"
3141 "#ifdef USEOFFSETMAPPING\n"
3142 " // apply offsetmapping\n"
3143 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3144 "#define TexCoord TexCoordOffset\n"
3147 " // combine the diffuse textures (base, pants, shirt)\n"
3148 " half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3149 "#ifdef USEALPHAKILL\n"
3150 " if (color.a < 0.5)\n"
3153 " color.a *= Alpha;\n"
3154 "#ifdef USECOLORMAPPING\n"
3155 " color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3157 "#ifdef USEVERTEXTEXTUREBLEND\n"
3158 " half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3159 " //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3160 " //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3161 " color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3163 " //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3166 " // get the surface normal\n"
3167 "#ifdef USEVERTEXTEXTUREBLEND\n"
3168 " half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3170 " half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3173 " // get the material colors\n"
3174 " half3 diffusetex = color.rgb;\n"
3175 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3176 "# ifdef USEVERTEXTEXTUREBLEND\n"
3177 " half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3179 " half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3183 "#ifdef USEREFLECTCUBE\n"
3184 " float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3185 " float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3186 " float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3187 " diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3193 "#ifdef MODE_LIGHTSOURCE\n"
3194 " // light source\n"
3195 "#ifdef USEDIFFUSE\n"
3196 " half3 lightnormal = half3(normalize(LightVector));\n"
3197 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3198 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3199 "#ifdef USESPECULAR\n"
3200 "#ifdef USEEXACTSPECULARMATH\n"
3201 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3203 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3204 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3206 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3209 " color.rgb = diffusetex * Color_Ambient;\n"
3211 " color.rgb *= LightColor;\n"
3212 " color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3213 "#if defined(USESHADOWMAP2D)\n"
3214 " color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3215 "#ifdef USESHADOWMAPVSDCT\n"
3216 ", Texture_CubeProjection\n"
3221 "# ifdef USECUBEFILTER\n"
3222 " color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3225 "#ifdef USESHADOWMAP2D\n"
3226 "#ifdef USESHADOWMAPVSDCT\n"
3227 "// float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3229 "// float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3231 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3232 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3233 "// color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3234 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3235 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3236 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3237 "// color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3238 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3239 "// color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3240 "// color.r = half(shadowmaptc.z);\n"
3241 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3242 "// color.r = half(shadowmaptc.z);\n"
3244 "// color.rgb = abs(CubeVector);\n"
3246 "// color.rgb = half3(1,1,1);\n"
3247 "#endif // MODE_LIGHTSOURCE\n"
3252 "#ifdef MODE_LIGHTDIRECTION\n"
3254 "#ifdef USEDIFFUSE\n"
3255 " half3 lightnormal = half3(normalize(LightVector));\n"
3257 "#define lightcolor LightColor\n"
3258 "#endif // MODE_LIGHTDIRECTION\n"
3259 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3261 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3262 " half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3263 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3264 " // convert modelspace light vector to tangentspace\n"
3265 " half3 lightnormal;\n"
3266 " lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3267 " lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3268 " lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3269 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3270 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3271 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3272 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3273 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3274 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3275 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3276 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3277 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3278 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3279 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3280 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3282 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3283 " half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3284 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3290 "#ifdef MODE_FAKELIGHT\n"
3292 "half3 lightnormal = half3(normalize(EyeVector));\n"
3293 "half3 lightcolor = half3(1.0,1.0,1.0);\n"
3294 "#endif // MODE_FAKELIGHT\n"
3299 "#ifdef MODE_LIGHTMAP\n"
3300 " color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3301 "#endif // MODE_LIGHTMAP\n"
3302 "#ifdef MODE_VERTEXCOLOR\n"
3303 " color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3304 "#endif // MODE_VERTEXCOLOR\n"
3305 "#ifdef MODE_FLATCOLOR\n"
3306 " color.rgb = diffusetex * Color_Ambient;\n"
3307 "#endif // MODE_FLATCOLOR\n"
3313 "# ifdef USEDIFFUSE\n"
3314 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3315 "# ifdef USESPECULAR\n"
3316 "# ifdef USEEXACTSPECULARMATH\n"
3317 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3319 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3320 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3322 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3324 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3327 " color.rgb = diffusetex * Color_Ambient;\n"
3331 "#ifdef USESHADOWMAPORTHO\n"
3332 " color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
3335 "#ifdef USEDEFERREDLIGHTMAP\n"
3336 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3337 " color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3338 " color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3339 "// color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
3340 "// color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
3344 "#ifdef USEVERTEXTEXTUREBLEND\n"
3345 " color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3347 " color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3352 " color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3355 " // 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"
3356 "#ifdef USEREFLECTION\n"
3357 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3358 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3359 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3360 " float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3361 " // FIXME temporary hack to detect the case that the reflection\n"
3362 " // gets blackened at edges due to leaving the area that contains actual\n"
3364 " // Remove this 'ack once we have a better way to stop this thing from\n"
3366 " float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3367 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3368 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3369 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3370 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3371 " color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3374 " gl_FragColor = float4(color);\n"
3376 "#endif // FRAGMENT_SHADER\n"
3378 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3379 "#endif // !MODE_DEFERREDGEOMETRY\n"
3380 "#endif // !MODE_WATER\n"
3381 "#endif // !MODE_REFRACTION\n"
3382 "#endif // !MODE_BLOOMBLUR\n"
3383 "#endif // !MODE_GENERIC\n"
3384 "#endif // !MODE_POSTPROCESS\n"
3385 "#endif // !MODE_SHOWDEPTH\n"
3386 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3389 char *glslshaderstring = NULL;
3390 char *hlslshaderstring = NULL;
3392 //=======================================================================================================================================================
3394 typedef struct shaderpermutationinfo_s
3396 const char *pretext;
3399 shaderpermutationinfo_t;
3401 typedef struct shadermodeinfo_s
3403 const char *vertexfilename;
3404 const char *geometryfilename;
3405 const char *fragmentfilename;
3406 const char *pretext;
3411 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3412 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3414 {"#define USEDIFFUSE\n", " diffuse"},
3415 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3416 {"#define USEVIEWTINT\n", " viewtint"},
3417 {"#define USECOLORMAPPING\n", " colormapping"},
3418 {"#define USESATURATION\n", " saturation"},
3419 {"#define USEFOGINSIDE\n", " foginside"},
3420 {"#define USEFOGOUTSIDE\n", " fogoutside"},
3421 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3422 {"#define USEGAMMARAMPS\n", " gammaramps"},
3423 {"#define USECUBEFILTER\n", " cubefilter"},
3424 {"#define USEGLOW\n", " glow"},
3425 {"#define USEBLOOM\n", " bloom"},
3426 {"#define USESPECULAR\n", " specular"},
3427 {"#define USEPOSTPROCESSING\n", " postprocessing"},
3428 {"#define USEREFLECTION\n", " reflection"},
3429 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3430 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3431 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3432 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3433 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3434 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3435 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3436 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3437 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3438 {"#define USEALPHAKILL\n", " alphakill"},
3439 {"#define USEREFLECTCUBE\n", " reflectcube"},
3440 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
3441 {"#define USEBOUNCEGRID\n", " bouncegrid"},
3444 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3445 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3447 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3448 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3449 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3450 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3451 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3452 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3453 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3454 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3455 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3456 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3457 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3458 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3459 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3460 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3461 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3462 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3463 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDBOUNCELIGHT\n", " deferredbouncelight"},
3466 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3468 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3469 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3470 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3471 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3472 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3473 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3474 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3475 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3476 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3477 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3478 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3479 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3480 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3481 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3482 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3483 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3484 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDBOUNCELIGHT\n", " deferredbouncelight"},
3487 struct r_glsl_permutation_s;
3488 typedef struct r_glsl_permutation_s
3490 /// hash lookup data
3491 struct r_glsl_permutation_s *hashnext;
3493 unsigned int permutation;
3495 /// indicates if we have tried compiling this permutation already
3497 /// 0 if compilation failed
3499 // texture units assigned to each detected uniform
3500 int tex_Texture_First;
3501 int tex_Texture_Second;
3502 int tex_Texture_GammaRamps;
3503 int tex_Texture_Normal;
3504 int tex_Texture_Color;
3505 int tex_Texture_Gloss;
3506 int tex_Texture_Glow;
3507 int tex_Texture_SecondaryNormal;
3508 int tex_Texture_SecondaryColor;
3509 int tex_Texture_SecondaryGloss;
3510 int tex_Texture_SecondaryGlow;
3511 int tex_Texture_Pants;
3512 int tex_Texture_Shirt;
3513 int tex_Texture_FogHeightTexture;
3514 int tex_Texture_FogMask;
3515 int tex_Texture_Lightmap;
3516 int tex_Texture_Deluxemap;
3517 int tex_Texture_Attenuation;
3518 int tex_Texture_Cube;
3519 int tex_Texture_Refraction;
3520 int tex_Texture_Reflection;
3521 int tex_Texture_ShadowMap2D;
3522 int tex_Texture_CubeProjection;
3523 int tex_Texture_ScreenDepth;
3524 int tex_Texture_ScreenNormalMap;
3525 int tex_Texture_ScreenDiffuse;
3526 int tex_Texture_ScreenSpecular;
3527 int tex_Texture_ReflectMask;
3528 int tex_Texture_ReflectCube;
3529 int tex_Texture_BounceGrid;
3530 /// locations of detected uniforms in program object, or -1 if not found
3531 int loc_Texture_First;
3532 int loc_Texture_Second;
3533 int loc_Texture_GammaRamps;
3534 int loc_Texture_Normal;
3535 int loc_Texture_Color;
3536 int loc_Texture_Gloss;
3537 int loc_Texture_Glow;
3538 int loc_Texture_SecondaryNormal;
3539 int loc_Texture_SecondaryColor;
3540 int loc_Texture_SecondaryGloss;
3541 int loc_Texture_SecondaryGlow;
3542 int loc_Texture_Pants;
3543 int loc_Texture_Shirt;
3544 int loc_Texture_FogHeightTexture;
3545 int loc_Texture_FogMask;
3546 int loc_Texture_Lightmap;
3547 int loc_Texture_Deluxemap;
3548 int loc_Texture_Attenuation;
3549 int loc_Texture_Cube;
3550 int loc_Texture_Refraction;
3551 int loc_Texture_Reflection;
3552 int loc_Texture_ShadowMap2D;
3553 int loc_Texture_CubeProjection;
3554 int loc_Texture_ScreenDepth;
3555 int loc_Texture_ScreenNormalMap;
3556 int loc_Texture_ScreenDiffuse;
3557 int loc_Texture_ScreenSpecular;
3558 int loc_Texture_ReflectMask;
3559 int loc_Texture_ReflectCube;
3560 int loc_Texture_BounceGrid;
3562 int loc_BloomBlur_Parameters;
3564 int loc_Color_Ambient;
3565 int loc_Color_Diffuse;
3566 int loc_Color_Specular;
3568 int loc_Color_Pants;
3569 int loc_Color_Shirt;
3570 int loc_DeferredColor_Ambient;
3571 int loc_DeferredColor_Diffuse;
3572 int loc_DeferredColor_Specular;
3573 int loc_DeferredMod_Diffuse;
3574 int loc_DeferredMod_Specular;
3575 int loc_DistortScaleRefractReflect;
3576 int loc_EyePosition;
3578 int loc_FogHeightFade;
3580 int loc_FogPlaneViewDist;
3581 int loc_FogRangeRecip;
3584 int loc_LightPosition;
3585 int loc_OffsetMapping_Scale;
3587 int loc_ReflectColor;
3588 int loc_ReflectFactor;
3589 int loc_ReflectOffset;
3590 int loc_RefractColor;
3592 int loc_ScreenCenterRefractReflect;
3593 int loc_ScreenScaleRefractReflect;
3594 int loc_ScreenToDepth;
3595 int loc_ShadowMap_Parameters;
3596 int loc_ShadowMap_TextureScale;
3597 int loc_SpecularPower;
3602 int loc_ViewTintColor;
3603 int loc_ViewToLight;
3604 int loc_ModelToLight;
3606 int loc_BackgroundTexMatrix;
3607 int loc_ModelViewProjectionMatrix;
3608 int loc_ModelViewMatrix;
3609 int loc_PixelToScreenTexCoord;
3610 int loc_ModelToReflectCube;
3611 int loc_ShadowMapMatrix;
3612 int loc_BloomColorSubtract;
3613 int loc_NormalmapScrollBlend;
3614 int loc_BounceGridMatrix;
3615 int loc_BounceGridIntensity;
3617 r_glsl_permutation_t;
3619 #define SHADERPERMUTATION_HASHSIZE 256
3622 // non-degradable "lightweight" shader parameters to keep the permutations simpler
3623 // these can NOT degrade! only use for simple stuff
3626 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
3627 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3628 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
3629 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
3630 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
3631 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5 ///< postprocess uservec4 is enabled
3633 #define SHADERSTATICPARMS_COUNT 6
3635 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
3636 static int shaderstaticparms_count = 0;
3638 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
3639 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
3640 qboolean R_CompileShader_CheckStaticParms(void)
3642 static int r_compileshader_staticparms_save[1];
3643 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
3644 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
3647 if (r_glsl_saturation_redcompensate.integer)
3648 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
3649 if (r_shadow_glossexact.integer)
3650 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
3651 if (r_glsl_postprocess.integer)
3653 if (r_glsl_postprocess_uservec1_enable.integer)
3654 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
3655 if (r_glsl_postprocess_uservec2_enable.integer)
3656 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
3657 if (r_glsl_postprocess_uservec3_enable.integer)
3658 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
3659 if (r_glsl_postprocess_uservec4_enable.integer)
3660 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
3662 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
3665 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
3666 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
3667 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
3669 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
3670 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
3672 shaderstaticparms_count = 0;
3675 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
3676 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
3677 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
3678 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
3679 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
3680 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
3683 /// information about each possible shader permutation
3684 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3685 /// currently selected permutation
3686 r_glsl_permutation_t *r_glsl_permutation;
3687 /// storage for permutations linked in the hash table
3688 memexpandablearray_t r_glsl_permutationarray;
3690 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3692 //unsigned int hashdepth = 0;
3693 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3694 r_glsl_permutation_t *p;
3695 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3697 if (p->mode == mode && p->permutation == permutation)
3699 //if (hashdepth > 10)
3700 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3705 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3707 p->permutation = permutation;
3708 p->hashnext = r_glsl_permutationhash[mode][hashindex];
3709 r_glsl_permutationhash[mode][hashindex] = p;
3710 //if (hashdepth > 10)
3711 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3715 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3718 if (!filename || !filename[0])
3720 if (!strcmp(filename, "glsl/default.glsl"))
3722 if (!glslshaderstring)
3724 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3725 if (glslshaderstring)
3726 Con_DPrintf("Loading shaders from file %s...\n", filename);
3728 glslshaderstring = (char *)builtinshaderstring;
3730 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3731 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3732 return shaderstring;
3734 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3737 if (printfromdisknotice)
3738 Con_DPrintf("from disk %s... ", filename);
3739 return shaderstring;
3741 return shaderstring;
3744 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3748 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3749 char *vertexstring, *geometrystring, *fragmentstring;
3750 char permutationname[256];
3751 int vertstrings_count = 0;
3752 int geomstrings_count = 0;
3753 int fragstrings_count = 0;
3754 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3755 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3756 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3763 permutationname[0] = 0;
3764 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
3765 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3766 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3768 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3770 // the first pretext is which type of shader to compile as
3771 // (later these will all be bound together as a program object)
3772 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3773 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3774 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3776 // the second pretext is the mode (for example a light source)
3777 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3778 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3779 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3780 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3782 // now add all the permutation pretexts
3783 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3785 if (permutation & (1<<i))
3787 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3788 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3789 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3790 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3794 // keep line numbers correct
3795 vertstrings_list[vertstrings_count++] = "\n";
3796 geomstrings_list[geomstrings_count++] = "\n";
3797 fragstrings_list[fragstrings_count++] = "\n";
3802 R_CompileShader_AddStaticParms(mode, permutation);
3803 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3804 vertstrings_count += shaderstaticparms_count;
3805 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3806 geomstrings_count += shaderstaticparms_count;
3807 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3808 fragstrings_count += shaderstaticparms_count;
3810 // now append the shader text itself
3811 vertstrings_list[vertstrings_count++] = vertexstring;
3812 geomstrings_list[geomstrings_count++] = geometrystring;
3813 fragstrings_list[fragstrings_count++] = fragmentstring;
3815 // if any sources were NULL, clear the respective list
3817 vertstrings_count = 0;
3818 if (!geometrystring)
3819 geomstrings_count = 0;
3820 if (!fragmentstring)
3821 fragstrings_count = 0;
3823 // compile the shader program
3824 if (vertstrings_count + geomstrings_count + fragstrings_count)
3825 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3829 qglUseProgram(p->program);CHECKGLERROR
3830 // look up all the uniform variable names we care about, so we don't
3831 // have to look them up every time we set them
3833 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
3834 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
3835 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
3836 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
3837 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
3838 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
3839 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
3840 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
3841 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
3842 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
3843 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
3844 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
3845 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
3846 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
3847 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
3848 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
3849 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
3850 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
3851 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
3852 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
3853 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
3854 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
3855 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
3856 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
3857 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
3858 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
3859 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
3860 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
3861 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
3862 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
3863 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
3864 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
3865 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
3866 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
3867 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
3868 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
3869 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
3870 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
3871 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
3872 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
3873 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
3874 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
3875 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
3876 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
3877 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
3878 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
3879 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
3880 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
3881 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
3882 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
3883 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
3884 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
3885 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
3886 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
3887 p->loc_OffsetMapping_Scale = qglGetUniformLocation(p->program, "OffsetMapping_Scale");
3888 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
3889 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
3890 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
3891 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
3892 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
3893 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
3894 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
3895 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
3896 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
3897 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
3898 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
3899 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
3900 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
3901 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
3902 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
3903 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
3904 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
3905 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
3906 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
3907 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
3908 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
3909 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
3910 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
3911 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
3912 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
3913 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
3914 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
3915 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
3916 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
3917 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
3918 // initialize the samplers to refer to the texture units we use
3919 p->tex_Texture_First = -1;
3920 p->tex_Texture_Second = -1;
3921 p->tex_Texture_GammaRamps = -1;
3922 p->tex_Texture_Normal = -1;
3923 p->tex_Texture_Color = -1;
3924 p->tex_Texture_Gloss = -1;
3925 p->tex_Texture_Glow = -1;
3926 p->tex_Texture_SecondaryNormal = -1;
3927 p->tex_Texture_SecondaryColor = -1;
3928 p->tex_Texture_SecondaryGloss = -1;
3929 p->tex_Texture_SecondaryGlow = -1;
3930 p->tex_Texture_Pants = -1;
3931 p->tex_Texture_Shirt = -1;
3932 p->tex_Texture_FogHeightTexture = -1;
3933 p->tex_Texture_FogMask = -1;
3934 p->tex_Texture_Lightmap = -1;
3935 p->tex_Texture_Deluxemap = -1;
3936 p->tex_Texture_Attenuation = -1;
3937 p->tex_Texture_Cube = -1;
3938 p->tex_Texture_Refraction = -1;
3939 p->tex_Texture_Reflection = -1;
3940 p->tex_Texture_ShadowMap2D = -1;
3941 p->tex_Texture_CubeProjection = -1;
3942 p->tex_Texture_ScreenDepth = -1;
3943 p->tex_Texture_ScreenNormalMap = -1;
3944 p->tex_Texture_ScreenDiffuse = -1;
3945 p->tex_Texture_ScreenSpecular = -1;
3946 p->tex_Texture_ReflectMask = -1;
3947 p->tex_Texture_ReflectCube = -1;
3948 p->tex_Texture_BounceGrid = -1;
3950 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
3951 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
3952 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
3953 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
3954 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
3955 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
3956 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
3957 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
3958 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
3959 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
3960 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
3961 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
3962 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
3963 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
3964 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
3965 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
3966 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
3967 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
3968 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
3969 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
3970 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
3971 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
3972 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
3973 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
3974 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
3975 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
3976 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
3977 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
3978 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
3979 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
3981 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
3984 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
3988 Mem_Free(vertexstring);
3990 Mem_Free(geometrystring);
3992 Mem_Free(fragmentstring);
3995 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3997 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3998 if (r_glsl_permutation != perm)
4000 r_glsl_permutation = perm;
4001 if (!r_glsl_permutation->program)
4003 if (!r_glsl_permutation->compiled)
4004 R_GLSL_CompilePermutation(perm, mode, permutation);
4005 if (!r_glsl_permutation->program)
4007 // remove features until we find a valid permutation
4009 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4011 // reduce i more quickly whenever it would not remove any bits
4012 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4013 if (!(permutation & j))
4016 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
4017 if (!r_glsl_permutation->compiled)
4018 R_GLSL_CompilePermutation(perm, mode, permutation);
4019 if (r_glsl_permutation->program)
4022 if (i >= SHADERPERMUTATION_COUNT)
4024 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4025 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
4026 qglUseProgram(0);CHECKGLERROR
4027 return; // no bit left to clear, entire mode is broken
4032 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
4034 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
4035 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
4036 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
4043 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4044 extern D3DCAPS9 vid_d3d9caps;
4047 struct r_hlsl_permutation_s;
4048 typedef struct r_hlsl_permutation_s
4050 /// hash lookup data
4051 struct r_hlsl_permutation_s *hashnext;
4053 unsigned int permutation;
4055 /// indicates if we have tried compiling this permutation already
4057 /// NULL if compilation failed
4058 IDirect3DVertexShader9 *vertexshader;
4059 IDirect3DPixelShader9 *pixelshader;
4061 r_hlsl_permutation_t;
4063 typedef enum D3DVSREGISTER_e
4065 D3DVSREGISTER_TexMatrix = 0, // float4x4
4066 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4067 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4068 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4069 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4070 D3DVSREGISTER_ModelToLight = 20, // float4x4
4071 D3DVSREGISTER_EyePosition = 24,
4072 D3DVSREGISTER_FogPlane = 25,
4073 D3DVSREGISTER_LightDir = 26,
4074 D3DVSREGISTER_LightPosition = 27,
4078 typedef enum D3DPSREGISTER_e
4080 D3DPSREGISTER_Alpha = 0,
4081 D3DPSREGISTER_BloomBlur_Parameters = 1,
4082 D3DPSREGISTER_ClientTime = 2,
4083 D3DPSREGISTER_Color_Ambient = 3,
4084 D3DPSREGISTER_Color_Diffuse = 4,
4085 D3DPSREGISTER_Color_Specular = 5,
4086 D3DPSREGISTER_Color_Glow = 6,
4087 D3DPSREGISTER_Color_Pants = 7,
4088 D3DPSREGISTER_Color_Shirt = 8,
4089 D3DPSREGISTER_DeferredColor_Ambient = 9,
4090 D3DPSREGISTER_DeferredColor_Diffuse = 10,
4091 D3DPSREGISTER_DeferredColor_Specular = 11,
4092 D3DPSREGISTER_DeferredMod_Diffuse = 12,
4093 D3DPSREGISTER_DeferredMod_Specular = 13,
4094 D3DPSREGISTER_DistortScaleRefractReflect = 14,
4095 D3DPSREGISTER_EyePosition = 15, // unused
4096 D3DPSREGISTER_FogColor = 16,
4097 D3DPSREGISTER_FogHeightFade = 17,
4098 D3DPSREGISTER_FogPlane = 18,
4099 D3DPSREGISTER_FogPlaneViewDist = 19,
4100 D3DPSREGISTER_FogRangeRecip = 20,
4101 D3DPSREGISTER_LightColor = 21,
4102 D3DPSREGISTER_LightDir = 22, // unused
4103 D3DPSREGISTER_LightPosition = 23,
4104 D3DPSREGISTER_OffsetMapping_Scale = 24,
4105 D3DPSREGISTER_PixelSize = 25,
4106 D3DPSREGISTER_ReflectColor = 26,
4107 D3DPSREGISTER_ReflectFactor = 27,
4108 D3DPSREGISTER_ReflectOffset = 28,
4109 D3DPSREGISTER_RefractColor = 29,
4110 D3DPSREGISTER_Saturation = 30,
4111 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4112 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4113 D3DPSREGISTER_ScreenToDepth = 33,
4114 D3DPSREGISTER_ShadowMap_Parameters = 34,
4115 D3DPSREGISTER_ShadowMap_TextureScale = 35,
4116 D3DPSREGISTER_SpecularPower = 36,
4117 D3DPSREGISTER_UserVec1 = 37,
4118 D3DPSREGISTER_UserVec2 = 38,
4119 D3DPSREGISTER_UserVec3 = 39,
4120 D3DPSREGISTER_UserVec4 = 40,
4121 D3DPSREGISTER_ViewTintColor = 41,
4122 D3DPSREGISTER_PixelToScreenTexCoord = 42,
4123 D3DPSREGISTER_BloomColorSubtract = 43,
4124 D3DPSREGISTER_ViewToLight = 44, // float4x4
4125 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4126 D3DPSREGISTER_NormalmapScrollBlend = 52,
4131 /// information about each possible shader permutation
4132 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4133 /// currently selected permutation
4134 r_hlsl_permutation_t *r_hlsl_permutation;
4135 /// storage for permutations linked in the hash table
4136 memexpandablearray_t r_hlsl_permutationarray;
4138 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4140 //unsigned int hashdepth = 0;
4141 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4142 r_hlsl_permutation_t *p;
4143 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4145 if (p->mode == mode && p->permutation == permutation)
4147 //if (hashdepth > 10)
4148 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4153 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4155 p->permutation = permutation;
4156 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4157 r_hlsl_permutationhash[mode][hashindex] = p;
4158 //if (hashdepth > 10)
4159 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4163 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4166 if (!filename || !filename[0])
4168 if (!strcmp(filename, "hlsl/default.hlsl"))
4170 if (!hlslshaderstring)
4172 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4173 if (hlslshaderstring)
4174 Con_DPrintf("Loading shaders from file %s...\n", filename);
4176 hlslshaderstring = (char *)builtinhlslshaderstring;
4178 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4179 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4180 return shaderstring;
4182 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4185 if (printfromdisknotice)
4186 Con_DPrintf("from disk %s... ", filename);
4187 return shaderstring;
4189 return shaderstring;
4193 //#include <d3dx9shader.h>
4194 //#include <d3dx9mesh.h>
4196 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4198 DWORD *vsbin = NULL;
4199 DWORD *psbin = NULL;
4200 fs_offset_t vsbinsize;
4201 fs_offset_t psbinsize;
4202 // IDirect3DVertexShader9 *vs = NULL;
4203 // IDirect3DPixelShader9 *ps = NULL;
4204 ID3DXBuffer *vslog = NULL;
4205 ID3DXBuffer *vsbuffer = NULL;
4206 ID3DXConstantTable *vsconstanttable = NULL;
4207 ID3DXBuffer *pslog = NULL;
4208 ID3DXBuffer *psbuffer = NULL;
4209 ID3DXConstantTable *psconstanttable = NULL;
4212 char temp[MAX_INPUTLINE];
4213 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4214 qboolean debugshader = gl_paranoid.integer != 0;
4215 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4216 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4219 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4220 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4222 if ((!vsbin && vertstring) || (!psbin && fragstring))
4224 const char* dllnames_d3dx9 [] =
4248 dllhandle_t d3dx9_dll = NULL;
4249 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4250 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4251 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4252 dllfunction_t d3dx9_dllfuncs[] =
4254 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
4255 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
4256 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
4259 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4261 DWORD shaderflags = 0;
4263 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4264 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4265 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4266 if (vertstring && vertstring[0])
4270 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4271 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4272 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4273 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4276 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4279 vsbinsize = vsbuffer->GetBufferSize();
4280 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4281 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4282 vsbuffer->Release();
4286 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4287 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4291 if (fragstring && fragstring[0])
4295 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4296 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4297 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4298 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4301 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4304 psbinsize = psbuffer->GetBufferSize();
4305 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4306 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4307 psbuffer->Release();
4311 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4312 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4316 Sys_UnloadLibrary(&d3dx9_dll);
4319 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4323 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4324 if (FAILED(vsresult))
4325 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4326 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4327 if (FAILED(psresult))
4328 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4330 // free the shader data
4331 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4332 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4335 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4338 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4339 int vertstring_length = 0;
4340 int geomstring_length = 0;
4341 int fragstring_length = 0;
4343 char *vertexstring, *geometrystring, *fragmentstring;
4344 char *vertstring, *geomstring, *fragstring;
4345 char permutationname[256];
4346 char cachename[256];
4347 int vertstrings_count = 0;
4348 int geomstrings_count = 0;
4349 int fragstrings_count = 0;
4350 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4351 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4352 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4357 p->vertexshader = NULL;
4358 p->pixelshader = NULL;
4360 permutationname[0] = 0;
4362 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
4363 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4364 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4366 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4367 strlcat(cachename, "hlsl/", sizeof(cachename));
4369 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4370 vertstrings_count = 0;
4371 geomstrings_count = 0;
4372 fragstrings_count = 0;
4373 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4374 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4375 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4377 // the first pretext is which type of shader to compile as
4378 // (later these will all be bound together as a program object)
4379 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4380 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4381 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4383 // the second pretext is the mode (for example a light source)
4384 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4385 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4386 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4387 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4388 strlcat(cachename, modeinfo->name, sizeof(cachename));
4390 // now add all the permutation pretexts
4391 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4393 if (permutation & (1<<i))
4395 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4396 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4397 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4398 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4399 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4403 // keep line numbers correct
4404 vertstrings_list[vertstrings_count++] = "\n";
4405 geomstrings_list[geomstrings_count++] = "\n";
4406 fragstrings_list[fragstrings_count++] = "\n";
4411 R_CompileShader_AddStaticParms(mode, permutation);
4412 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4413 vertstrings_count += shaderstaticparms_count;
4414 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4415 geomstrings_count += shaderstaticparms_count;
4416 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4417 fragstrings_count += shaderstaticparms_count;
4419 // replace spaces in the cachename with _ characters
4420 for (i = 0;cachename[i];i++)
4421 if (cachename[i] == ' ')
4424 // now append the shader text itself
4425 vertstrings_list[vertstrings_count++] = vertexstring;
4426 geomstrings_list[geomstrings_count++] = geometrystring;
4427 fragstrings_list[fragstrings_count++] = fragmentstring;
4429 // if any sources were NULL, clear the respective list
4431 vertstrings_count = 0;
4432 if (!geometrystring)
4433 geomstrings_count = 0;
4434 if (!fragmentstring)
4435 fragstrings_count = 0;
4437 vertstring_length = 0;
4438 for (i = 0;i < vertstrings_count;i++)
4439 vertstring_length += strlen(vertstrings_list[i]);
4440 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4441 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4442 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4444 geomstring_length = 0;
4445 for (i = 0;i < geomstrings_count;i++)
4446 geomstring_length += strlen(geomstrings_list[i]);
4447 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4448 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4449 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4451 fragstring_length = 0;
4452 for (i = 0;i < fragstrings_count;i++)
4453 fragstring_length += strlen(fragstrings_list[i]);
4454 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4455 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4456 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4458 // try to load the cached shader, or generate one
4459 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4461 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4462 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4464 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
4468 Mem_Free(vertstring);
4470 Mem_Free(geomstring);
4472 Mem_Free(fragstring);
4474 Mem_Free(vertexstring);
4476 Mem_Free(geometrystring);
4478 Mem_Free(fragmentstring);
4481 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4482 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4483 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);}
4484 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);}
4485 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);}
4486 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);}
4488 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4489 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4490 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);}
4491 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);}
4492 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);}
4493 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);}
4495 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4497 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4498 if (r_hlsl_permutation != perm)
4500 r_hlsl_permutation = perm;
4501 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4503 if (!r_hlsl_permutation->compiled)
4504 R_HLSL_CompilePermutation(perm, mode, permutation);
4505 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4507 // remove features until we find a valid permutation
4509 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4511 // reduce i more quickly whenever it would not remove any bits
4512 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4513 if (!(permutation & j))
4516 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4517 if (!r_hlsl_permutation->compiled)
4518 R_HLSL_CompilePermutation(perm, mode, permutation);
4519 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4522 if (i >= SHADERPERMUTATION_COUNT)
4524 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4525 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4526 return; // no bit left to clear, entire mode is broken
4530 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4531 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4533 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4534 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4535 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4539 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
4541 DPSOFTRAST_SetShader(mode, permutation);
4542 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
4543 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
4544 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
4547 void R_GLSL_Restart_f(void)
4549 unsigned int i, limit;
4550 if (glslshaderstring && glslshaderstring != builtinshaderstring)
4551 Mem_Free(glslshaderstring);
4552 glslshaderstring = NULL;
4553 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
4554 Mem_Free(hlslshaderstring);
4555 hlslshaderstring = NULL;
4556 switch(vid.renderpath)
4558 case RENDERPATH_D3D9:
4561 r_hlsl_permutation_t *p;
4562 r_hlsl_permutation = NULL;
4563 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
4564 for (i = 0;i < limit;i++)
4566 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
4568 if (p->vertexshader)
4569 IDirect3DVertexShader9_Release(p->vertexshader);
4571 IDirect3DPixelShader9_Release(p->pixelshader);
4572 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
4575 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4579 case RENDERPATH_D3D10:
4580 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4582 case RENDERPATH_D3D11:
4583 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4585 case RENDERPATH_GL20:
4586 case RENDERPATH_GLES2:
4588 r_glsl_permutation_t *p;
4589 r_glsl_permutation = NULL;
4590 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4591 for (i = 0;i < limit;i++)
4593 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4595 GL_Backend_FreeProgram(p->program);
4596 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4599 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4602 case RENDERPATH_GL13:
4603 case RENDERPATH_GL11:
4605 case RENDERPATH_SOFT:
4610 void R_GLSL_DumpShader_f(void)
4615 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4618 FS_Print(file, "/* The engine may define the following macros:\n");
4619 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4620 for (i = 0;i < SHADERMODE_COUNT;i++)
4621 FS_Print(file, glslshadermodeinfo[i].pretext);
4622 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4623 FS_Print(file, shaderpermutationinfo[i].pretext);
4624 FS_Print(file, "*/\n");
4625 FS_Print(file, builtinshaderstring);
4627 Con_Printf("glsl/default.glsl written\n");
4630 Con_Printf("failed to write to glsl/default.glsl\n");
4632 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
4635 FS_Print(file, "/* The engine may define the following macros:\n");
4636 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4637 for (i = 0;i < SHADERMODE_COUNT;i++)
4638 FS_Print(file, hlslshadermodeinfo[i].pretext);
4639 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4640 FS_Print(file, shaderpermutationinfo[i].pretext);
4641 FS_Print(file, "*/\n");
4642 FS_Print(file, builtinhlslshaderstring);
4644 Con_Printf("hlsl/default.hlsl written\n");
4647 Con_Printf("failed to write to hlsl/default.hlsl\n");
4650 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4653 texturemode = GL_MODULATE;
4654 switch (vid.renderpath)
4656 case RENDERPATH_D3D9:
4658 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))));
4659 R_Mesh_TexBind(GL20TU_FIRST , first );
4660 R_Mesh_TexBind(GL20TU_SECOND, second);
4663 case RENDERPATH_D3D10:
4664 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4666 case RENDERPATH_D3D11:
4667 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4669 case RENDERPATH_GL20:
4670 case RENDERPATH_GLES2:
4671 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))));
4672 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
4673 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
4675 case RENDERPATH_GL13:
4676 R_Mesh_TexBind(0, first );
4677 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4678 R_Mesh_TexBind(1, second);
4680 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4682 case RENDERPATH_GL11:
4683 R_Mesh_TexBind(0, first );
4685 case RENDERPATH_SOFT:
4686 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))));
4687 R_Mesh_TexBind(GL20TU_FIRST , first );
4688 R_Mesh_TexBind(GL20TU_SECOND, second);
4693 void R_SetupShader_DepthOrShadow(void)
4695 switch (vid.renderpath)
4697 case RENDERPATH_D3D9:
4699 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4702 case RENDERPATH_D3D10:
4703 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4705 case RENDERPATH_D3D11:
4706 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4708 case RENDERPATH_GL20:
4709 case RENDERPATH_GLES2:
4710 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4712 case RENDERPATH_GL13:
4713 R_Mesh_TexBind(0, 0);
4714 R_Mesh_TexBind(1, 0);
4716 case RENDERPATH_GL11:
4717 R_Mesh_TexBind(0, 0);
4719 case RENDERPATH_SOFT:
4720 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
4725 void R_SetupShader_ShowDepth(void)
4727 switch (vid.renderpath)
4729 case RENDERPATH_D3D9:
4731 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
4734 case RENDERPATH_D3D10:
4735 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4737 case RENDERPATH_D3D11:
4738 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4740 case RENDERPATH_GL20:
4741 case RENDERPATH_GLES2:
4742 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4744 case RENDERPATH_GL13:
4746 case RENDERPATH_GL11:
4748 case RENDERPATH_SOFT:
4749 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
4754 extern qboolean r_shadow_usingdeferredprepass;
4755 extern cvar_t r_shadow_deferred_8bitrange;
4756 extern rtexture_t *r_shadow_attenuationgradienttexture;
4757 extern rtexture_t *r_shadow_attenuation2dtexture;
4758 extern rtexture_t *r_shadow_attenuation3dtexture;
4759 extern qboolean r_shadow_usingshadowmap2d;
4760 extern qboolean r_shadow_usingshadowmaportho;
4761 extern float r_shadow_shadowmap_texturescale[2];
4762 extern float r_shadow_shadowmap_parameters[4];
4763 extern qboolean r_shadow_shadowmapvsdct;
4764 extern qboolean r_shadow_shadowmapsampler;
4765 extern int r_shadow_shadowmappcf;
4766 extern rtexture_t *r_shadow_shadowmap2dtexture;
4767 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
4768 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4769 extern matrix4x4_t r_shadow_shadowmapmatrix;
4770 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4771 extern int r_shadow_prepass_width;
4772 extern int r_shadow_prepass_height;
4773 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4774 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4775 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
4776 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4777 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4778 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
4780 // a blendfunc allows colormod if:
4781 // a) it can never keep the destination pixel invariant, or
4782 // b) it can keep the destination pixel invariant, and still can do so if colormodded
4783 // this is to prevent unintended side effects from colormod
4786 // IF there is a (s, sa) for which for all (d, da),
4787 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
4788 // THEN, for this (s, sa) and all (colormod, d, da):
4789 // s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
4790 // OBVIOUSLY, this means that
4791 // s*colormod * src(s*colormod, d, sa, da) = 0
4792 // dst(s*colormod, d, sa, da) = 1
4794 // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
4796 // main condition to leave dst color invariant:
4797 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
4799 // s * 0 + d * dst(s, d, sa, da) == d
4800 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4801 // => colormod is a problem for GL_SRC_COLOR only
4803 // s + d * dst(s, d, sa, da) == d
4805 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4806 // => colormod is never problematic for these
4807 // src == GL_SRC_COLOR:
4808 // s*s + d * dst(s, d, sa, da) == d
4810 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4811 // => colormod is never problematic for these
4812 // src == GL_ONE_MINUS_SRC_COLOR:
4813 // s*(1-s) + d * dst(s, d, sa, da) == d
4814 // => s == 0 or s == 1
4815 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4816 // => colormod is a problem for GL_SRC_COLOR only
4817 // src == GL_DST_COLOR
4818 // s*d + d * dst(s, d, sa, da) == d
4820 // => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4821 // => colormod is always a problem
4824 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4825 // => colormod is never problematic for these
4826 // => BUT, we do not know s! We must assume it is problematic
4827 // then... except in GL_ONE case, where we know all invariant
4829 // src == GL_ONE_MINUS_DST_COLOR
4830 // s*(1-d) + d * dst(s, d, sa, da) == d
4831 // => s == 0 (1-d is impossible to handle for our desired result)
4832 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4833 // => colormod is never problematic for these
4834 // src == GL_SRC_ALPHA
4835 // s*sa + d * dst(s, d, sa, da) == d
4836 // => s == 0, or sa == 0
4837 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4838 // => colormod breaks in the case GL_SRC_COLOR only
4839 // src == GL_ONE_MINUS_SRC_ALPHA
4840 // s*(1-sa) + d * dst(s, d, sa, da) == d
4841 // => s == 0, or sa == 1
4842 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4843 // => colormod breaks in the case GL_SRC_COLOR only
4844 // src == GL_DST_ALPHA
4845 // s*da + d * dst(s, d, sa, da) == d
4847 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4848 // => colormod is never problematic for these
4853 case GL_ONE_MINUS_SRC_COLOR:
4855 case GL_ONE_MINUS_SRC_ALPHA:
4856 if(dst == GL_SRC_COLOR)
4861 case GL_ONE_MINUS_DST_COLOR:
4863 case GL_ONE_MINUS_DST_ALPHA:
4873 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)
4875 // select a permutation of the lighting shader appropriate to this
4876 // combination of texture, entity, light source, and fogging, only use the
4877 // minimum features necessary to avoid wasting rendering time in the
4878 // fragment shader on features that are not being used
4879 unsigned int permutation = 0;
4880 unsigned int mode = 0;
4881 qboolean allow_colormod;
4882 static float dummy_colormod[3] = {1, 1, 1};
4883 float *colormod = rsurface.colormod;
4885 matrix4x4_t tempmatrix;
4886 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
4887 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4888 permutation |= SHADERPERMUTATION_ALPHAKILL;
4889 if (rsurfacepass == RSURFPASS_BACKGROUND)
4891 // distorted background
4892 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4894 mode = SHADERMODE_WATER;
4895 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
4896 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
4897 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
4899 // this is the right thing to do for wateralpha
4900 GL_BlendFunc(GL_ONE, GL_ZERO);
4901 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4905 // this is the right thing to do for entity alpha
4906 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4907 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4910 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
4912 mode = SHADERMODE_REFRACTION;
4913 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4914 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4918 mode = SHADERMODE_GENERIC;
4919 permutation |= SHADERPERMUTATION_DIFFUSE;
4920 GL_BlendFunc(GL_ONE, GL_ZERO);
4921 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4924 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4926 if (r_glsl_offsetmapping.integer)
4928 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4929 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4930 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4931 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4932 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4934 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4935 if (r_glsl_offsetmapping_reliefmapping.integer)
4936 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4939 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4940 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4941 // normalmap (deferred prepass), may use alpha test on diffuse
4942 mode = SHADERMODE_DEFERREDGEOMETRY;
4943 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4944 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4945 GL_BlendFunc(GL_ONE, GL_ZERO);
4946 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4948 else if (rsurfacepass == RSURFPASS_RTLIGHT)
4950 if (r_glsl_offsetmapping.integer)
4952 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4953 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4954 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4955 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4956 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4958 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4959 if (r_glsl_offsetmapping_reliefmapping.integer)
4960 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4963 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4964 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4966 mode = SHADERMODE_LIGHTSOURCE;
4967 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4968 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4969 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4970 permutation |= SHADERPERMUTATION_CUBEFILTER;
4971 if (diffusescale > 0)
4972 permutation |= SHADERPERMUTATION_DIFFUSE;
4973 if (specularscale > 0)
4974 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4975 if (r_refdef.fogenabled)
4976 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4977 if (rsurface.texture->colormapping)
4978 permutation |= SHADERPERMUTATION_COLORMAPPING;
4979 if (r_shadow_usingshadowmap2d)
4981 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4982 if(r_shadow_shadowmapvsdct)
4983 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4985 if (r_shadow_shadowmapsampler)
4986 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4987 if (r_shadow_shadowmappcf > 1)
4988 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4989 else if (r_shadow_shadowmappcf)
4990 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4992 if (rsurface.texture->reflectmasktexture)
4993 permutation |= SHADERPERMUTATION_REFLECTCUBE;
4994 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4995 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
4997 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4999 if (r_glsl_offsetmapping.integer)
5001 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5002 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5003 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5004 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5005 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5007 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5008 if (r_glsl_offsetmapping_reliefmapping.integer)
5009 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5012 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5013 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5014 // unshaded geometry (fullbright or ambient model lighting)
5015 mode = SHADERMODE_FLATCOLOR;
5016 ambientscale = diffusescale = specularscale = 0;
5017 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5018 permutation |= SHADERPERMUTATION_GLOW;
5019 if (r_refdef.fogenabled)
5020 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5021 if (rsurface.texture->colormapping)
5022 permutation |= SHADERPERMUTATION_COLORMAPPING;
5023 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5025 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5026 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5028 if (r_shadow_shadowmapsampler)
5029 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5030 if (r_shadow_shadowmappcf > 1)
5031 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5032 else if (r_shadow_shadowmappcf)
5033 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5035 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5036 permutation |= SHADERPERMUTATION_REFLECTION;
5037 if (rsurface.texture->reflectmasktexture)
5038 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5039 if (r_shadow_bouncegridtexture)
5040 permutation |= SHADERPERMUTATION_BOUNCEGRID;
5041 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5042 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5044 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5046 if (r_glsl_offsetmapping.integer)
5048 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5049 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5050 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5051 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5052 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5054 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5055 if (r_glsl_offsetmapping_reliefmapping.integer)
5056 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5059 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5060 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5061 // directional model lighting
5062 mode = SHADERMODE_LIGHTDIRECTION;
5063 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5064 permutation |= SHADERPERMUTATION_GLOW;
5065 permutation |= SHADERPERMUTATION_DIFFUSE;
5066 if (specularscale > 0)
5067 permutation |= SHADERPERMUTATION_SPECULAR;
5068 if (r_refdef.fogenabled)
5069 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5070 if (rsurface.texture->colormapping)
5071 permutation |= SHADERPERMUTATION_COLORMAPPING;
5072 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5074 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5075 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5077 if (r_shadow_shadowmapsampler)
5078 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5079 if (r_shadow_shadowmappcf > 1)
5080 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5081 else if (r_shadow_shadowmappcf)
5082 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5084 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5085 permutation |= SHADERPERMUTATION_REFLECTION;
5086 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5087 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5088 if (rsurface.texture->reflectmasktexture)
5089 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5090 if (r_shadow_bouncegridtexture)
5091 permutation |= SHADERPERMUTATION_BOUNCEGRID;
5092 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5093 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5095 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5097 if (r_glsl_offsetmapping.integer)
5099 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5100 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5101 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5102 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5103 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5105 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5106 if (r_glsl_offsetmapping_reliefmapping.integer)
5107 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5110 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5111 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5112 // ambient model lighting
5113 mode = SHADERMODE_LIGHTDIRECTION;
5114 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5115 permutation |= SHADERPERMUTATION_GLOW;
5116 if (r_refdef.fogenabled)
5117 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5118 if (rsurface.texture->colormapping)
5119 permutation |= SHADERPERMUTATION_COLORMAPPING;
5120 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5122 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5123 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5125 if (r_shadow_shadowmapsampler)
5126 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5127 if (r_shadow_shadowmappcf > 1)
5128 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5129 else if (r_shadow_shadowmappcf)
5130 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5132 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5133 permutation |= SHADERPERMUTATION_REFLECTION;
5134 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5135 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5136 if (rsurface.texture->reflectmasktexture)
5137 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5138 if (r_shadow_bouncegridtexture)
5139 permutation |= SHADERPERMUTATION_BOUNCEGRID;
5140 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5141 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5145 if (r_glsl_offsetmapping.integer)
5147 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5148 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5149 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5150 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5151 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5153 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5154 if (r_glsl_offsetmapping_reliefmapping.integer)
5155 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5158 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5159 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5161 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5162 permutation |= SHADERPERMUTATION_GLOW;
5163 if (r_refdef.fogenabled)
5164 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5165 if (rsurface.texture->colormapping)
5166 permutation |= SHADERPERMUTATION_COLORMAPPING;
5167 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5169 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5170 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5172 if (r_shadow_shadowmapsampler)
5173 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5174 if (r_shadow_shadowmappcf > 1)
5175 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5176 else if (r_shadow_shadowmappcf)
5177 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5179 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5180 permutation |= SHADERPERMUTATION_REFLECTION;
5181 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5182 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5183 if (rsurface.texture->reflectmasktexture)
5184 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5185 if (FAKELIGHT_ENABLED)
5187 // fake lightmapping (q1bsp, q3bsp, fullbright map)
5188 mode = SHADERMODE_FAKELIGHT;
5189 permutation |= SHADERPERMUTATION_DIFFUSE;
5190 if (specularscale > 0)
5191 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5193 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5195 // deluxemapping (light direction texture)
5196 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5197 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5199 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5200 permutation |= SHADERPERMUTATION_DIFFUSE;
5201 if (specularscale > 0)
5202 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5204 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5206 // fake deluxemapping (uniform light direction in tangentspace)
5207 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5208 permutation |= SHADERPERMUTATION_DIFFUSE;
5209 if (specularscale > 0)
5210 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5212 else if (rsurface.uselightmaptexture)
5214 // ordinary lightmapping (q1bsp, q3bsp)
5215 mode = SHADERMODE_LIGHTMAP;
5219 // ordinary vertex coloring (q3bsp)
5220 mode = SHADERMODE_VERTEXCOLOR;
5222 if (r_shadow_bouncegridtexture)
5223 permutation |= SHADERPERMUTATION_BOUNCEGRID;
5224 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5225 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5228 colormod = dummy_colormod;
5229 switch(vid.renderpath)
5231 case RENDERPATH_D3D9:
5233 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);
5234 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5235 R_SetupShader_SetPermutationHLSL(mode, permutation);
5236 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5237 if (mode == SHADERMODE_LIGHTSOURCE)
5239 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5240 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5244 if (mode == SHADERMODE_LIGHTDIRECTION)
5246 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5249 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5250 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5251 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5252 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5253 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5255 if (mode == SHADERMODE_LIGHTSOURCE)
5257 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5258 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5259 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5260 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5261 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5263 // additive passes are only darkened by fog, not tinted
5264 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5265 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5269 if (mode == SHADERMODE_FLATCOLOR)
5271 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5273 else if (mode == SHADERMODE_LIGHTDIRECTION)
5275 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]);
5276 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5277 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);
5278 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);
5279 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5280 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5281 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5285 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5286 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5287 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);
5288 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);
5289 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5291 // additive passes are only darkened by fog, not tinted
5292 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5293 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5295 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5296 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);
5297 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5298 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5299 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5300 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5301 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5302 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5303 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5304 if (mode == SHADERMODE_WATER)
5305 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5307 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5308 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5309 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5310 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));
5311 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5312 if (rsurface.texture->pantstexture)
5313 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5315 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5316 if (rsurface.texture->shirttexture)
5317 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5319 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5320 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5321 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5322 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5323 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5324 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5325 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5326 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5328 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5329 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5330 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5331 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5332 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5333 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5334 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5335 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5336 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5337 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5338 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5339 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5340 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5341 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5342 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5343 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5344 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5345 if (rsurfacepass == RSURFPASS_BACKGROUND)
5347 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5348 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5349 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5353 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5355 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5356 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5357 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5358 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5359 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5361 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5362 if (rsurface.rtlight)
5364 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5365 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5370 case RENDERPATH_D3D10:
5371 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5373 case RENDERPATH_D3D11:
5374 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5376 case RENDERPATH_GL20:
5377 case RENDERPATH_GLES2:
5378 if (!vid.useinterleavedarrays)
5380 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);
5381 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5382 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5383 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5384 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5385 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5386 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5387 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5391 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);
5392 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5394 R_SetupShader_SetPermutationGLSL(mode, permutation);
5395 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5396 if (mode == SHADERMODE_LIGHTSOURCE)
5398 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5399 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5400 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5401 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5402 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5403 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);
5405 // additive passes are only darkened by fog, not tinted
5406 if (r_glsl_permutation->loc_FogColor >= 0)
5407 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5408 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5412 if (mode == SHADERMODE_FLATCOLOR)
5414 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5416 else if (mode == SHADERMODE_LIGHTDIRECTION)
5418 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]);
5419 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]);
5420 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);
5421 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);
5422 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);
5423 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]);
5424 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]);
5428 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]);
5429 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]);
5430 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);
5431 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);
5432 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);
5434 // additive passes are only darkened by fog, not tinted
5435 if (r_glsl_permutation->loc_FogColor >= 0)
5437 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5438 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5440 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5442 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);
5443 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]);
5444 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]);
5445 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]);
5446 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]);
5447 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5448 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5449 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5450 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]);
5452 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5453 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5454 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5455 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]);
5456 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]);
5458 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5459 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));
5460 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5461 if (r_glsl_permutation->loc_Color_Pants >= 0)
5463 if (rsurface.texture->pantstexture)
5464 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5466 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5468 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5470 if (rsurface.texture->shirttexture)
5471 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5473 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5475 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]);
5476 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5477 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5478 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5479 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5480 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]);
5481 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5482 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);}
5483 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity);
5485 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
5486 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
5487 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
5488 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
5489 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
5490 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
5491 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
5492 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
5493 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
5494 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
5495 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
5496 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
5497 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
5498 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
5499 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);
5500 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
5501 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
5502 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5503 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5504 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
5505 if (rsurfacepass == RSURFPASS_BACKGROUND)
5507 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);
5508 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);
5509 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);
5513 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);
5515 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
5516 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
5517 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
5518 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
5519 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5521 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
5522 if (rsurface.rtlight)
5524 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
5525 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
5528 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
5531 case RENDERPATH_GL13:
5532 case RENDERPATH_GL11:
5534 case RENDERPATH_SOFT:
5535 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);
5536 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
5537 R_SetupShader_SetPermutationSoft(mode, permutation);
5538 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
5539 if (mode == SHADERMODE_LIGHTSOURCE)
5541 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
5542 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5543 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5544 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5545 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5546 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5548 // additive passes are only darkened by fog, not tinted
5549 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
5550 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5554 if (mode == SHADERMODE_FLATCOLOR)
5556 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5558 else if (mode == SHADERMODE_LIGHTDIRECTION)
5560 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]);
5561 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5562 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);
5563 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);
5564 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5565 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]);
5566 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5570 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5571 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5572 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);
5573 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);
5574 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5576 // additive passes are only darkened by fog, not tinted
5577 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5578 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
5580 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5581 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);
5582 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5583 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5584 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]);
5585 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]);
5586 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5587 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
5588 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5589 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5591 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
5592 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
5593 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
5594 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5595 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]);
5597 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5598 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));
5599 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5600 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
5602 if (rsurface.texture->pantstexture)
5603 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5605 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
5607 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
5609 if (rsurface.texture->shirttexture)
5610 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5612 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
5614 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5615 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
5616 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
5617 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
5618 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5619 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5620 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5622 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5623 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5624 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5625 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5626 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5627 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5628 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5629 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5630 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5631 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5632 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5633 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5634 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5635 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5636 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5637 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5638 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5639 if (rsurfacepass == RSURFPASS_BACKGROUND)
5641 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5642 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5643 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5647 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5649 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5650 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5651 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5652 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5653 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5655 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5656 if (rsurface.rtlight)
5658 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5659 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5666 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5668 // select a permutation of the lighting shader appropriate to this
5669 // combination of texture, entity, light source, and fogging, only use the
5670 // minimum features necessary to avoid wasting rendering time in the
5671 // fragment shader on features that are not being used
5672 unsigned int permutation = 0;
5673 unsigned int mode = 0;
5674 const float *lightcolorbase = rtlight->currentcolor;
5675 float ambientscale = rtlight->ambientscale;
5676 float diffusescale = rtlight->diffusescale;
5677 float specularscale = rtlight->specularscale;
5678 // this is the location of the light in view space
5679 vec3_t viewlightorigin;
5680 // this transforms from view space (camera) to light space (cubemap)
5681 matrix4x4_t viewtolight;
5682 matrix4x4_t lighttoview;
5683 float viewtolight16f[16];
5684 float range = 1.0f / r_shadow_deferred_8bitrange.value;
5686 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
5687 if (rtlight->currentcubemap != r_texture_whitecube)
5688 permutation |= SHADERPERMUTATION_CUBEFILTER;
5689 if (diffusescale > 0)
5690 permutation |= SHADERPERMUTATION_DIFFUSE;
5691 if (specularscale > 0)
5692 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5693 if (r_shadow_usingshadowmap2d)
5695 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5696 if (r_shadow_shadowmapvsdct)
5697 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5699 if (r_shadow_shadowmapsampler)
5700 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5701 if (r_shadow_shadowmappcf > 1)
5702 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5703 else if (r_shadow_shadowmappcf)
5704 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5706 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
5707 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
5708 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
5709 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
5710 switch(vid.renderpath)
5712 case RENDERPATH_D3D9:
5714 R_SetupShader_SetPermutationHLSL(mode, permutation);
5715 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5716 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
5717 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
5718 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
5719 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
5720 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5721 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5722 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5723 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5724 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5726 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5727 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
5728 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5729 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5730 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
5731 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5734 case RENDERPATH_D3D10:
5735 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5737 case RENDERPATH_D3D11:
5738 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5740 case RENDERPATH_GL20:
5741 case RENDERPATH_GLES2:
5742 R_SetupShader_SetPermutationGLSL(mode, permutation);
5743 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5744 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
5745 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);
5746 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);
5747 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);
5748 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]);
5749 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]);
5750 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));
5751 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]);
5752 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
5754 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
5755 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
5756 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
5757 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
5758 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
5759 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
5761 case RENDERPATH_GL13:
5762 case RENDERPATH_GL11:
5764 case RENDERPATH_SOFT:
5765 R_SetupShader_SetPermutationGLSL(mode, permutation);
5766 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5767 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
5768 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
5769 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
5770 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
5771 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5772 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]);
5773 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));
5774 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5775 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5777 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5778 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5779 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5780 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5781 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
5782 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5787 void R_SetupShader_DeferredBounceLight(void)
5789 // array of particle lights that contribute only ambient color
5790 unsigned int permutation = 0;
5791 unsigned int mode = 0;
5792 mode = SHADERMODE_DEFERREDBOUNCELIGHT;
5793 switch(vid.renderpath)
5795 case RENDERPATH_D3D9:
5797 R_SetupShader_SetPermutationHLSL(mode, permutation);
5798 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5799 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5801 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
5804 case RENDERPATH_D3D10:
5805 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5807 case RENDERPATH_D3D11:
5808 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5810 case RENDERPATH_GL20:
5811 case RENDERPATH_GLES2:
5812 R_SetupShader_SetPermutationGLSL(mode, permutation);
5813 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]);
5814 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
5816 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
5818 case RENDERPATH_GL13:
5819 case RENDERPATH_GL11:
5821 case RENDERPATH_SOFT:
5822 R_SetupShader_SetPermutationGLSL(mode, permutation);
5823 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5824 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5826 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5831 #define SKINFRAME_HASH 1024
5835 int loadsequence; // incremented each level change
5836 memexpandablearray_t array;
5837 skinframe_t *hash[SKINFRAME_HASH];
5840 r_skinframe_t r_skinframe;
5842 void R_SkinFrame_PrepareForPurge(void)
5844 r_skinframe.loadsequence++;
5845 // wrap it without hitting zero
5846 if (r_skinframe.loadsequence >= 200)
5847 r_skinframe.loadsequence = 1;
5850 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5854 // mark the skinframe as used for the purging code
5855 skinframe->loadsequence = r_skinframe.loadsequence;
5858 void R_SkinFrame_Purge(void)
5862 for (i = 0;i < SKINFRAME_HASH;i++)
5864 for (s = r_skinframe.hash[i];s;s = s->next)
5866 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5868 if (s->merged == s->base)
5870 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5871 R_PurgeTexture(s->stain );s->stain = NULL;
5872 R_PurgeTexture(s->merged);s->merged = NULL;
5873 R_PurgeTexture(s->base );s->base = NULL;
5874 R_PurgeTexture(s->pants );s->pants = NULL;
5875 R_PurgeTexture(s->shirt );s->shirt = NULL;
5876 R_PurgeTexture(s->nmap );s->nmap = NULL;
5877 R_PurgeTexture(s->gloss );s->gloss = NULL;
5878 R_PurgeTexture(s->glow );s->glow = NULL;
5879 R_PurgeTexture(s->fog );s->fog = NULL;
5880 R_PurgeTexture(s->reflect);s->reflect = NULL;
5881 s->loadsequence = 0;
5887 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5889 char basename[MAX_QPATH];
5891 Image_StripImageExtension(name, basename, sizeof(basename));
5893 if( last == NULL ) {
5895 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5896 item = r_skinframe.hash[hashindex];
5901 // linearly search through the hash bucket
5902 for( ; item ; item = item->next ) {
5903 if( !strcmp( item->basename, basename ) ) {
5910 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5914 char basename[MAX_QPATH];
5916 Image_StripImageExtension(name, basename, sizeof(basename));
5918 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5919 for (item = r_skinframe.hash[hashindex];item;item = item->next)
5920 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5924 rtexture_t *dyntexture;
5925 // check whether its a dynamic texture
5926 dyntexture = CL_GetDynTexture( basename );
5927 if (!add && !dyntexture)
5929 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5930 memset(item, 0, sizeof(*item));
5931 strlcpy(item->basename, basename, sizeof(item->basename));
5932 item->base = dyntexture; // either NULL or dyntexture handle
5933 item->textureflags = textureflags;
5934 item->comparewidth = comparewidth;
5935 item->compareheight = compareheight;
5936 item->comparecrc = comparecrc;
5937 item->next = r_skinframe.hash[hashindex];
5938 r_skinframe.hash[hashindex] = item;
5940 else if( item->base == NULL )
5942 rtexture_t *dyntexture;
5943 // check whether its a dynamic texture
5944 // 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]
5945 dyntexture = CL_GetDynTexture( basename );
5946 item->base = dyntexture; // either NULL or dyntexture handle
5949 R_SkinFrame_MarkUsed(item);
5953 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5955 unsigned long long avgcolor[5], wsum; \
5963 for(pix = 0; pix < cnt; ++pix) \
5966 for(comp = 0; comp < 3; ++comp) \
5968 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5971 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5973 for(comp = 0; comp < 3; ++comp) \
5974 avgcolor[comp] += getpixel * w; \
5977 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5978 avgcolor[4] += getpixel; \
5980 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5982 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5983 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5984 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5985 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5988 extern cvar_t gl_picmip;
5989 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5992 unsigned char *pixels;
5993 unsigned char *bumppixels;
5994 unsigned char *basepixels = NULL;
5995 int basepixels_width = 0;
5996 int basepixels_height = 0;
5997 skinframe_t *skinframe;
5998 rtexture_t *ddsbase = NULL;
5999 qboolean ddshasalpha = false;
6000 float ddsavgcolor[4];
6001 char basename[MAX_QPATH];
6002 int miplevel = R_PicmipForFlags(textureflags);
6003 int savemiplevel = miplevel;
6006 if (cls.state == ca_dedicated)
6009 // return an existing skinframe if already loaded
6010 // if loading of the first image fails, don't make a new skinframe as it
6011 // would cause all future lookups of this to be missing
6012 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6013 if (skinframe && skinframe->base)
6016 Image_StripImageExtension(name, basename, sizeof(basename));
6018 // check for DDS texture file first
6019 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6021 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6022 if (basepixels == NULL)
6026 // FIXME handle miplevel
6028 if (developer_loading.integer)
6029 Con_Printf("loading skin \"%s\"\n", name);
6031 // we've got some pixels to store, so really allocate this new texture now
6033 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6034 skinframe->stain = NULL;
6035 skinframe->merged = NULL;
6036 skinframe->base = NULL;
6037 skinframe->pants = NULL;
6038 skinframe->shirt = NULL;
6039 skinframe->nmap = NULL;
6040 skinframe->gloss = NULL;
6041 skinframe->glow = NULL;
6042 skinframe->fog = NULL;
6043 skinframe->reflect = NULL;
6044 skinframe->hasalpha = false;
6048 skinframe->base = ddsbase;
6049 skinframe->hasalpha = ddshasalpha;
6050 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6051 if (r_loadfog && skinframe->hasalpha)
6052 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6053 //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]);
6057 basepixels_width = image_width;
6058 basepixels_height = image_height;
6059 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);
6060 if (textureflags & TEXF_ALPHA)
6062 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6064 if (basepixels[j] < 255)
6066 skinframe->hasalpha = true;
6070 if (r_loadfog && skinframe->hasalpha)
6072 // has transparent pixels
6073 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6074 for (j = 0;j < image_width * image_height * 4;j += 4)
6079 pixels[j+3] = basepixels[j+3];
6081 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);
6085 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6086 //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]);
6087 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6088 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6089 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6090 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6095 mymiplevel = savemiplevel;
6096 if (r_loadnormalmap)
6097 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);
6098 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6100 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6101 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6102 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6103 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6106 // _norm is the name used by tenebrae and has been adopted as standard
6107 if (r_loadnormalmap && skinframe->nmap == NULL)
6109 mymiplevel = savemiplevel;
6110 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6112 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);
6116 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6118 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6119 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6120 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);
6122 Mem_Free(bumppixels);
6124 else if (r_shadow_bumpscale_basetexture.value > 0)
6126 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6127 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6128 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);
6131 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6132 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6135 // _luma is supported only for tenebrae compatibility
6136 // _glow is the preferred name
6137 mymiplevel = savemiplevel;
6138 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))))
6140 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);
6141 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6142 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6143 Mem_Free(pixels);pixels = NULL;
6146 mymiplevel = savemiplevel;
6147 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6149 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);
6150 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6151 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6156 mymiplevel = savemiplevel;
6157 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6159 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);
6160 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6161 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6166 mymiplevel = savemiplevel;
6167 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6169 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);
6170 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6171 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6176 mymiplevel = savemiplevel;
6177 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6179 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);
6180 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6181 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6187 Mem_Free(basepixels);
6192 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6193 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6196 unsigned char *temp1, *temp2;
6197 skinframe_t *skinframe;
6199 if (cls.state == ca_dedicated)
6202 // if already loaded just return it, otherwise make a new skinframe
6203 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6204 if (skinframe && skinframe->base)
6207 skinframe->stain = NULL;
6208 skinframe->merged = NULL;
6209 skinframe->base = NULL;
6210 skinframe->pants = NULL;
6211 skinframe->shirt = NULL;
6212 skinframe->nmap = NULL;
6213 skinframe->gloss = NULL;
6214 skinframe->glow = NULL;
6215 skinframe->fog = NULL;
6216 skinframe->reflect = NULL;
6217 skinframe->hasalpha = false;
6219 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6223 if (developer_loading.integer)
6224 Con_Printf("loading 32bit skin \"%s\"\n", name);
6226 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6228 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6229 temp2 = temp1 + width * height * 4;
6230 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6231 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);
6234 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6235 if (textureflags & TEXF_ALPHA)
6237 for (i = 3;i < width * height * 4;i += 4)
6239 if (skindata[i] < 255)
6241 skinframe->hasalpha = true;
6245 if (r_loadfog && skinframe->hasalpha)
6247 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6248 memcpy(fogpixels, skindata, width * height * 4);
6249 for (i = 0;i < width * height * 4;i += 4)
6250 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6251 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6252 Mem_Free(fogpixels);
6256 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6257 //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]);
6262 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6266 skinframe_t *skinframe;
6268 if (cls.state == ca_dedicated)
6271 // if already loaded just return it, otherwise make a new skinframe
6272 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6273 if (skinframe && skinframe->base)
6276 skinframe->stain = NULL;
6277 skinframe->merged = NULL;
6278 skinframe->base = NULL;
6279 skinframe->pants = NULL;
6280 skinframe->shirt = NULL;
6281 skinframe->nmap = NULL;
6282 skinframe->gloss = NULL;
6283 skinframe->glow = NULL;
6284 skinframe->fog = NULL;
6285 skinframe->reflect = NULL;
6286 skinframe->hasalpha = false;
6288 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6292 if (developer_loading.integer)
6293 Con_Printf("loading quake skin \"%s\"\n", name);
6295 // 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)
6296 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
6297 memcpy(skinframe->qpixels, skindata, width*height);
6298 skinframe->qwidth = width;
6299 skinframe->qheight = height;
6302 for (i = 0;i < width * height;i++)
6303 featuresmask |= palette_featureflags[skindata[i]];
6305 skinframe->hasalpha = false;
6306 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6307 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6308 skinframe->qgeneratemerged = true;
6309 skinframe->qgeneratebase = skinframe->qhascolormapping;
6310 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6312 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6313 //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]);
6318 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6322 unsigned char *skindata;
6324 if (!skinframe->qpixels)
6327 if (!skinframe->qhascolormapping)
6328 colormapped = false;
6332 if (!skinframe->qgeneratebase)
6337 if (!skinframe->qgeneratemerged)
6341 width = skinframe->qwidth;
6342 height = skinframe->qheight;
6343 skindata = skinframe->qpixels;
6345 if (skinframe->qgeneratenmap)
6347 unsigned char *temp1, *temp2;
6348 skinframe->qgeneratenmap = false;
6349 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6350 temp2 = temp1 + width * height * 4;
6351 // use either a custom palette or the quake palette
6352 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6353 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6354 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);
6358 if (skinframe->qgenerateglow)
6360 skinframe->qgenerateglow = false;
6361 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6366 skinframe->qgeneratebase = false;
6367 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);
6368 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6369 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6373 skinframe->qgeneratemerged = false;
6374 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);
6377 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6379 Mem_Free(skinframe->qpixels);
6380 skinframe->qpixels = NULL;
6384 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)
6387 skinframe_t *skinframe;
6389 if (cls.state == ca_dedicated)
6392 // if already loaded just return it, otherwise make a new skinframe
6393 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6394 if (skinframe && skinframe->base)
6397 skinframe->stain = NULL;
6398 skinframe->merged = NULL;
6399 skinframe->base = NULL;
6400 skinframe->pants = NULL;
6401 skinframe->shirt = NULL;
6402 skinframe->nmap = NULL;
6403 skinframe->gloss = NULL;
6404 skinframe->glow = NULL;
6405 skinframe->fog = NULL;
6406 skinframe->reflect = NULL;
6407 skinframe->hasalpha = false;
6409 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6413 if (developer_loading.integer)
6414 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6416 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6417 if (textureflags & TEXF_ALPHA)
6419 for (i = 0;i < width * height;i++)
6421 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6423 skinframe->hasalpha = true;
6427 if (r_loadfog && skinframe->hasalpha)
6428 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6431 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6432 //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]);
6437 skinframe_t *R_SkinFrame_LoadMissing(void)
6439 skinframe_t *skinframe;
6441 if (cls.state == ca_dedicated)
6444 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6445 skinframe->stain = NULL;
6446 skinframe->merged = NULL;
6447 skinframe->base = NULL;
6448 skinframe->pants = NULL;
6449 skinframe->shirt = NULL;
6450 skinframe->nmap = NULL;
6451 skinframe->gloss = NULL;
6452 skinframe->glow = NULL;
6453 skinframe->fog = NULL;
6454 skinframe->reflect = NULL;
6455 skinframe->hasalpha = false;
6457 skinframe->avgcolor[0] = rand() / RAND_MAX;
6458 skinframe->avgcolor[1] = rand() / RAND_MAX;
6459 skinframe->avgcolor[2] = rand() / RAND_MAX;
6460 skinframe->avgcolor[3] = 1;
6465 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6466 typedef struct suffixinfo_s
6469 qboolean flipx, flipy, flipdiagonal;
6472 static suffixinfo_t suffix[3][6] =
6475 {"px", false, false, false},
6476 {"nx", false, false, false},
6477 {"py", false, false, false},
6478 {"ny", false, false, false},
6479 {"pz", false, false, false},
6480 {"nz", false, false, false}
6483 {"posx", false, false, false},
6484 {"negx", false, false, false},
6485 {"posy", false, false, false},
6486 {"negy", false, false, false},
6487 {"posz", false, false, false},
6488 {"negz", false, false, false}
6491 {"rt", true, false, true},
6492 {"lf", false, true, true},
6493 {"ft", true, true, false},
6494 {"bk", false, false, false},
6495 {"up", true, false, true},
6496 {"dn", true, false, true}
6500 static int componentorder[4] = {0, 1, 2, 3};
6502 rtexture_t *R_LoadCubemap(const char *basename)
6504 int i, j, cubemapsize;
6505 unsigned char *cubemappixels, *image_buffer;
6506 rtexture_t *cubemaptexture;
6508 // must start 0 so the first loadimagepixels has no requested width/height
6510 cubemappixels = NULL;
6511 cubemaptexture = NULL;
6512 // keep trying different suffix groups (posx, px, rt) until one loads
6513 for (j = 0;j < 3 && !cubemappixels;j++)
6515 // load the 6 images in the suffix group
6516 for (i = 0;i < 6;i++)
6518 // generate an image name based on the base and and suffix
6519 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6521 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
6523 // an image loaded, make sure width and height are equal
6524 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6526 // if this is the first image to load successfully, allocate the cubemap memory
6527 if (!cubemappixels && image_width >= 1)
6529 cubemapsize = image_width;
6530 // note this clears to black, so unavailable sides are black
6531 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6533 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6535 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);
6538 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6540 Mem_Free(image_buffer);
6544 // if a cubemap loaded, upload it
6547 if (developer_loading.integer)
6548 Con_Printf("loading cubemap \"%s\"\n", basename);
6550 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6551 Mem_Free(cubemappixels);
6555 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6556 if (developer_loading.integer)
6558 Con_Printf("(tried tried images ");
6559 for (j = 0;j < 3;j++)
6560 for (i = 0;i < 6;i++)
6561 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6562 Con_Print(" and was unable to find any of them).\n");
6565 return cubemaptexture;
6568 rtexture_t *R_GetCubemap(const char *basename)
6571 for (i = 0;i < r_texture_numcubemaps;i++)
6572 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6573 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6574 if (i >= MAX_CUBEMAPS)
6575 return r_texture_whitecube;
6576 r_texture_numcubemaps++;
6577 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6578 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6579 return r_texture_cubemaps[i].texture;
6582 void R_FreeCubemaps(void)
6585 for (i = 0;i < r_texture_numcubemaps;i++)
6587 if (developer_loading.integer)
6588 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6589 if (r_texture_cubemaps[i].texture)
6590 R_FreeTexture(r_texture_cubemaps[i].texture);
6592 r_texture_numcubemaps = 0;
6595 void R_Main_FreeViewCache(void)
6597 if (r_refdef.viewcache.entityvisible)
6598 Mem_Free(r_refdef.viewcache.entityvisible);
6599 if (r_refdef.viewcache.world_pvsbits)
6600 Mem_Free(r_refdef.viewcache.world_pvsbits);
6601 if (r_refdef.viewcache.world_leafvisible)
6602 Mem_Free(r_refdef.viewcache.world_leafvisible);
6603 if (r_refdef.viewcache.world_surfacevisible)
6604 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6605 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6608 void R_Main_ResizeViewCache(void)
6610 int numentities = r_refdef.scene.numentities;
6611 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6612 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6613 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6614 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6615 if (r_refdef.viewcache.maxentities < numentities)
6617 r_refdef.viewcache.maxentities = numentities;
6618 if (r_refdef.viewcache.entityvisible)
6619 Mem_Free(r_refdef.viewcache.entityvisible);
6620 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6622 if (r_refdef.viewcache.world_numclusters != numclusters)
6624 r_refdef.viewcache.world_numclusters = numclusters;
6625 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6626 if (r_refdef.viewcache.world_pvsbits)
6627 Mem_Free(r_refdef.viewcache.world_pvsbits);
6628 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6630 if (r_refdef.viewcache.world_numleafs != numleafs)
6632 r_refdef.viewcache.world_numleafs = numleafs;
6633 if (r_refdef.viewcache.world_leafvisible)
6634 Mem_Free(r_refdef.viewcache.world_leafvisible);
6635 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6637 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6639 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6640 if (r_refdef.viewcache.world_surfacevisible)
6641 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6642 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6646 extern rtexture_t *loadingscreentexture;
6647 void gl_main_start(void)
6649 loadingscreentexture = NULL;
6650 r_texture_blanknormalmap = NULL;
6651 r_texture_white = NULL;
6652 r_texture_grey128 = NULL;
6653 r_texture_black = NULL;
6654 r_texture_whitecube = NULL;
6655 r_texture_normalizationcube = NULL;
6656 r_texture_fogattenuation = NULL;
6657 r_texture_fogheighttexture = NULL;
6658 r_texture_gammaramps = NULL;
6659 r_texture_numcubemaps = 0;
6661 r_loaddds = r_texture_dds_load.integer != 0;
6662 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6664 switch(vid.renderpath)
6666 case RENDERPATH_GL20:
6667 case RENDERPATH_D3D9:
6668 case RENDERPATH_D3D10:
6669 case RENDERPATH_D3D11:
6670 case RENDERPATH_SOFT:
6671 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6672 Cvar_SetValueQuick(&gl_combine, 1);
6673 Cvar_SetValueQuick(&r_glsl, 1);
6674 r_loadnormalmap = true;
6678 case RENDERPATH_GL13:
6679 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6680 Cvar_SetValueQuick(&gl_combine, 1);
6681 Cvar_SetValueQuick(&r_glsl, 0);
6682 r_loadnormalmap = false;
6683 r_loadgloss = false;
6686 case RENDERPATH_GL11:
6687 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6688 Cvar_SetValueQuick(&gl_combine, 0);
6689 Cvar_SetValueQuick(&r_glsl, 0);
6690 r_loadnormalmap = false;
6691 r_loadgloss = false;
6694 case RENDERPATH_GLES2:
6695 Cvar_SetValueQuick(&r_textureunits, 1);
6696 Cvar_SetValueQuick(&gl_combine, 1);
6697 Cvar_SetValueQuick(&r_glsl, 1);
6698 r_loadnormalmap = true;
6699 r_loadgloss = false;
6705 R_FrameData_Reset();
6709 memset(r_queries, 0, sizeof(r_queries));
6711 r_qwskincache = NULL;
6712 r_qwskincache_size = 0;
6714 // set up r_skinframe loading system for textures
6715 memset(&r_skinframe, 0, sizeof(r_skinframe));
6716 r_skinframe.loadsequence = 1;
6717 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6719 r_main_texturepool = R_AllocTexturePool();
6720 R_BuildBlankTextures();
6722 if (vid.support.arb_texture_cube_map)
6725 R_BuildNormalizationCube();
6727 r_texture_fogattenuation = NULL;
6728 r_texture_fogheighttexture = NULL;
6729 r_texture_gammaramps = NULL;
6730 //r_texture_fogintensity = NULL;
6731 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6732 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_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
6736 glslshaderstring = NULL;
6738 r_hlsl_permutation = NULL;
6739 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
6740 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
6742 hlslshaderstring = NULL;
6743 memset(&r_svbsp, 0, sizeof (r_svbsp));
6745 r_refdef.fogmasktable_density = 0;
6748 void gl_main_shutdown(void)
6751 R_FrameData_Reset();
6753 R_Main_FreeViewCache();
6755 switch(vid.renderpath)
6757 case RENDERPATH_GL11:
6758 case RENDERPATH_GL13:
6759 case RENDERPATH_GL20:
6760 case RENDERPATH_GLES2:
6762 qglDeleteQueriesARB(r_maxqueries, r_queries);
6764 case RENDERPATH_D3D9:
6765 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6767 case RENDERPATH_D3D10:
6768 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6770 case RENDERPATH_D3D11:
6771 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6773 case RENDERPATH_SOFT:
6779 memset(r_queries, 0, sizeof(r_queries));
6781 r_qwskincache = NULL;
6782 r_qwskincache_size = 0;
6784 // clear out the r_skinframe state
6785 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
6786 memset(&r_skinframe, 0, sizeof(r_skinframe));
6789 Mem_Free(r_svbsp.nodes);
6790 memset(&r_svbsp, 0, sizeof (r_svbsp));
6791 R_FreeTexturePool(&r_main_texturepool);
6792 loadingscreentexture = NULL;
6793 r_texture_blanknormalmap = NULL;
6794 r_texture_white = NULL;
6795 r_texture_grey128 = NULL;
6796 r_texture_black = NULL;
6797 r_texture_whitecube = NULL;
6798 r_texture_normalizationcube = NULL;
6799 r_texture_fogattenuation = NULL;
6800 r_texture_fogheighttexture = NULL;
6801 r_texture_gammaramps = NULL;
6802 r_texture_numcubemaps = 0;
6803 //r_texture_fogintensity = NULL;
6804 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6805 memset(&r_waterstate, 0, sizeof(r_waterstate));
6808 r_glsl_permutation = NULL;
6809 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6810 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
6811 glslshaderstring = NULL;
6813 r_hlsl_permutation = NULL;
6814 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
6815 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
6817 hlslshaderstring = NULL;
6820 extern void CL_ParseEntityLump(char *entitystring);
6821 void gl_main_newmap(void)
6823 // FIXME: move this code to client
6824 char *entities, entname[MAX_QPATH];
6826 Mem_Free(r_qwskincache);
6827 r_qwskincache = NULL;
6828 r_qwskincache_size = 0;
6831 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
6832 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
6834 CL_ParseEntityLump(entities);
6838 if (cl.worldmodel->brush.entities)
6839 CL_ParseEntityLump(cl.worldmodel->brush.entities);
6841 R_Main_FreeViewCache();
6843 R_FrameData_Reset();
6846 void GL_Main_Init(void)
6848 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
6850 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
6851 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
6852 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
6853 if (gamemode == GAME_NEHAHRA)
6855 Cvar_RegisterVariable (&gl_fogenable);
6856 Cvar_RegisterVariable (&gl_fogdensity);
6857 Cvar_RegisterVariable (&gl_fogred);
6858 Cvar_RegisterVariable (&gl_foggreen);
6859 Cvar_RegisterVariable (&gl_fogblue);
6860 Cvar_RegisterVariable (&gl_fogstart);
6861 Cvar_RegisterVariable (&gl_fogend);
6862 Cvar_RegisterVariable (&gl_skyclip);
6864 Cvar_RegisterVariable(&r_motionblur);
6865 Cvar_RegisterVariable(&r_motionblur_maxblur);
6866 Cvar_RegisterVariable(&r_motionblur_bmin);
6867 Cvar_RegisterVariable(&r_motionblur_vmin);
6868 Cvar_RegisterVariable(&r_motionblur_vmax);
6869 Cvar_RegisterVariable(&r_motionblur_vcoeff);
6870 Cvar_RegisterVariable(&r_motionblur_randomize);
6871 Cvar_RegisterVariable(&r_damageblur);
6872 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
6873 Cvar_RegisterVariable(&r_equalize_entities_minambient);
6874 Cvar_RegisterVariable(&r_equalize_entities_by);
6875 Cvar_RegisterVariable(&r_equalize_entities_to);
6876 Cvar_RegisterVariable(&r_depthfirst);
6877 Cvar_RegisterVariable(&r_useinfinitefarclip);
6878 Cvar_RegisterVariable(&r_farclip_base);
6879 Cvar_RegisterVariable(&r_farclip_world);
6880 Cvar_RegisterVariable(&r_nearclip);
6881 Cvar_RegisterVariable(&r_showbboxes);
6882 Cvar_RegisterVariable(&r_showsurfaces);
6883 Cvar_RegisterVariable(&r_showtris);
6884 Cvar_RegisterVariable(&r_shownormals);
6885 Cvar_RegisterVariable(&r_showlighting);
6886 Cvar_RegisterVariable(&r_showshadowvolumes);
6887 Cvar_RegisterVariable(&r_showcollisionbrushes);
6888 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
6889 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
6890 Cvar_RegisterVariable(&r_showdisabledepthtest);
6891 Cvar_RegisterVariable(&r_drawportals);
6892 Cvar_RegisterVariable(&r_drawentities);
6893 Cvar_RegisterVariable(&r_draw2d);
6894 Cvar_RegisterVariable(&r_drawworld);
6895 Cvar_RegisterVariable(&r_cullentities_trace);
6896 Cvar_RegisterVariable(&r_cullentities_trace_samples);
6897 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
6898 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
6899 Cvar_RegisterVariable(&r_cullentities_trace_delay);
6900 Cvar_RegisterVariable(&r_drawviewmodel);
6901 Cvar_RegisterVariable(&r_drawexteriormodel);
6902 Cvar_RegisterVariable(&r_speeds);
6903 Cvar_RegisterVariable(&r_fullbrights);
6904 Cvar_RegisterVariable(&r_wateralpha);
6905 Cvar_RegisterVariable(&r_dynamic);
6906 Cvar_RegisterVariable(&r_fakelight);
6907 Cvar_RegisterVariable(&r_fakelight_intensity);
6908 Cvar_RegisterVariable(&r_fullbright);
6909 Cvar_RegisterVariable(&r_shadows);
6910 Cvar_RegisterVariable(&r_shadows_darken);
6911 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
6912 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
6913 Cvar_RegisterVariable(&r_shadows_throwdistance);
6914 Cvar_RegisterVariable(&r_shadows_throwdirection);
6915 Cvar_RegisterVariable(&r_shadows_focus);
6916 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
6917 Cvar_RegisterVariable(&r_q1bsp_skymasking);
6918 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
6919 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
6920 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
6921 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
6922 Cvar_RegisterVariable(&r_fog_exp2);
6923 Cvar_RegisterVariable(&r_drawfog);
6924 Cvar_RegisterVariable(&r_transparentdepthmasking);
6925 Cvar_RegisterVariable(&r_texture_dds_load);
6926 Cvar_RegisterVariable(&r_texture_dds_save);
6927 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
6928 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
6929 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
6930 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
6931 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
6932 Cvar_RegisterVariable(&r_textureunits);
6933 Cvar_RegisterVariable(&gl_combine);
6934 Cvar_RegisterVariable(&r_glsl);
6935 Cvar_RegisterVariable(&r_glsl_deluxemapping);
6936 Cvar_RegisterVariable(&r_glsl_offsetmapping);
6937 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
6938 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
6939 Cvar_RegisterVariable(&r_glsl_postprocess);
6940 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
6941 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
6942 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
6943 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
6944 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
6945 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
6946 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
6947 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
6949 Cvar_RegisterVariable(&r_water);
6950 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
6951 Cvar_RegisterVariable(&r_water_clippingplanebias);
6952 Cvar_RegisterVariable(&r_water_refractdistort);
6953 Cvar_RegisterVariable(&r_water_reflectdistort);
6954 Cvar_RegisterVariable(&r_water_scissormode);
6955 Cvar_RegisterVariable(&r_lerpsprites);
6956 Cvar_RegisterVariable(&r_lerpmodels);
6957 Cvar_RegisterVariable(&r_lerplightstyles);
6958 Cvar_RegisterVariable(&r_waterscroll);
6959 Cvar_RegisterVariable(&r_bloom);
6960 Cvar_RegisterVariable(&r_bloom_colorscale);
6961 Cvar_RegisterVariable(&r_bloom_brighten);
6962 Cvar_RegisterVariable(&r_bloom_blur);
6963 Cvar_RegisterVariable(&r_bloom_resolution);
6964 Cvar_RegisterVariable(&r_bloom_colorexponent);
6965 Cvar_RegisterVariable(&r_bloom_colorsubtract);
6966 Cvar_RegisterVariable(&r_hdr);
6967 Cvar_RegisterVariable(&r_hdr_scenebrightness);
6968 Cvar_RegisterVariable(&r_hdr_glowintensity);
6969 Cvar_RegisterVariable(&r_hdr_range);
6970 Cvar_RegisterVariable(&r_hdr_irisadaptation);
6971 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
6972 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
6973 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
6974 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
6975 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
6976 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
6977 Cvar_RegisterVariable(&developer_texturelogging);
6978 Cvar_RegisterVariable(&gl_lightmaps);
6979 Cvar_RegisterVariable(&r_test);
6980 Cvar_RegisterVariable(&r_glsl_saturation);
6981 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
6982 Cvar_RegisterVariable(&r_framedatasize);
6983 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
6984 Cvar_SetValue("r_fullbrights", 0);
6985 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
6987 Cvar_RegisterVariable(&r_track_sprites);
6988 Cvar_RegisterVariable(&r_track_sprites_flags);
6989 Cvar_RegisterVariable(&r_track_sprites_scalew);
6990 Cvar_RegisterVariable(&r_track_sprites_scaleh);
6991 Cvar_RegisterVariable(&r_overheadsprites_perspective);
6992 Cvar_RegisterVariable(&r_overheadsprites_pushback);
6993 Cvar_RegisterVariable(&r_overheadsprites_scalex);
6994 Cvar_RegisterVariable(&r_overheadsprites_scaley);
6997 extern void R_Textures_Init(void);
6998 extern void GL_Draw_Init(void);
6999 extern void GL_Main_Init(void);
7000 extern void R_Shadow_Init(void);
7001 extern void R_Sky_Init(void);
7002 extern void GL_Surf_Init(void);
7003 extern void R_Particles_Init(void);
7004 extern void R_Explosion_Init(void);
7005 extern void gl_backend_init(void);
7006 extern void Sbar_Init(void);
7007 extern void R_LightningBeams_Init(void);
7008 extern void Mod_RenderInit(void);
7009 extern void Font_Init(void);
7011 void Render_Init(void)
7024 R_LightningBeams_Init();
7033 extern char *ENGINE_EXTENSIONS;
7036 gl_renderer = (const char *)qglGetString(GL_RENDERER);
7037 gl_vendor = (const char *)qglGetString(GL_VENDOR);
7038 gl_version = (const char *)qglGetString(GL_VERSION);
7039 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7043 if (!gl_platformextensions)
7044 gl_platformextensions = "";
7046 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7047 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7048 Con_Printf("GL_VERSION: %s\n", gl_version);
7049 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7050 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7052 VID_CheckExtensions();
7054 // LordHavoc: report supported extensions
7055 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7057 // clear to black (loading plaque will be seen over this)
7058 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7061 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7065 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7067 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7070 p = r_refdef.view.frustum + i;
7075 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7079 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7083 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7087 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7091 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7095 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7099 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7103 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7111 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7115 for (i = 0;i < numplanes;i++)
7122 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7126 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7130 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7134 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7138 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7142 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7146 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7150 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7158 //==================================================================================
7160 // LordHavoc: this stores temporary data used within the same frame
7162 typedef struct r_framedata_mem_s
7164 struct r_framedata_mem_s *purge; // older mem block to free on next frame
7165 size_t size; // how much usable space
7166 size_t current; // how much space in use
7167 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
7168 size_t wantedsize; // how much space was allocated
7169 unsigned char *data; // start of real data (16byte aligned)
7173 static r_framedata_mem_t *r_framedata_mem;
7175 void R_FrameData_Reset(void)
7177 while (r_framedata_mem)
7179 r_framedata_mem_t *next = r_framedata_mem->purge;
7180 Mem_Free(r_framedata_mem);
7181 r_framedata_mem = next;
7185 void R_FrameData_Resize(void)
7188 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7189 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
7190 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
7192 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
7193 newmem->wantedsize = wantedsize;
7194 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
7195 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
7196 newmem->current = 0;
7198 newmem->purge = r_framedata_mem;
7199 r_framedata_mem = newmem;
7203 void R_FrameData_NewFrame(void)
7205 R_FrameData_Resize();
7206 if (!r_framedata_mem)
7208 // if we ran out of space on the last frame, free the old memory now
7209 while (r_framedata_mem->purge)
7211 // repeatedly remove the second item in the list, leaving only head
7212 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
7213 Mem_Free(r_framedata_mem->purge);
7214 r_framedata_mem->purge = next;
7216 // reset the current mem pointer
7217 r_framedata_mem->current = 0;
7218 r_framedata_mem->mark = 0;
7221 void *R_FrameData_Alloc(size_t size)
7225 // align to 16 byte boundary - the data pointer is already aligned, so we
7226 // only need to ensure the size of every allocation is also aligned
7227 size = (size + 15) & ~15;
7229 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
7231 // emergency - we ran out of space, allocate more memory
7232 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
7233 R_FrameData_Resize();
7236 data = r_framedata_mem->data + r_framedata_mem->current;
7237 r_framedata_mem->current += size;
7239 // count the usage for stats
7240 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
7241 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
7243 return (void *)data;
7246 void *R_FrameData_Store(size_t size, void *data)
7248 void *d = R_FrameData_Alloc(size);
7250 memcpy(d, data, size);
7254 void R_FrameData_SetMark(void)
7256 if (!r_framedata_mem)
7258 r_framedata_mem->mark = r_framedata_mem->current;
7261 void R_FrameData_ReturnToMark(void)
7263 if (!r_framedata_mem)
7265 r_framedata_mem->current = r_framedata_mem->mark;
7268 //==================================================================================
7270 // LordHavoc: animcache originally written by Echon, rewritten since then
7273 * Animation cache prevents re-generating mesh data for an animated model
7274 * multiple times in one frame for lighting, shadowing, reflections, etc.
7277 void R_AnimCache_Free(void)
7281 void R_AnimCache_ClearCache(void)
7284 entity_render_t *ent;
7286 for (i = 0;i < r_refdef.scene.numentities;i++)
7288 ent = r_refdef.scene.entities[i];
7289 ent->animcache_vertex3f = NULL;
7290 ent->animcache_normal3f = NULL;
7291 ent->animcache_svector3f = NULL;
7292 ent->animcache_tvector3f = NULL;
7293 ent->animcache_vertexmesh = NULL;
7294 ent->animcache_vertex3fbuffer = NULL;
7295 ent->animcache_vertexmeshbuffer = NULL;
7299 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7303 // check if we need the meshbuffers
7304 if (!vid.useinterleavedarrays)
7307 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7308 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7309 // TODO: upload vertex3f buffer?
7310 if (ent->animcache_vertexmesh)
7312 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7313 for (i = 0;i < numvertices;i++)
7314 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7315 if (ent->animcache_svector3f)
7316 for (i = 0;i < numvertices;i++)
7317 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7318 if (ent->animcache_tvector3f)
7319 for (i = 0;i < numvertices;i++)
7320 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7321 if (ent->animcache_normal3f)
7322 for (i = 0;i < numvertices;i++)
7323 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7324 // TODO: upload vertexmeshbuffer?
7328 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7330 dp_model_t *model = ent->model;
7332 // see if it's already cached this frame
7333 if (ent->animcache_vertex3f)
7335 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7336 if (wantnormals || wanttangents)
7338 if (ent->animcache_normal3f)
7339 wantnormals = false;
7340 if (ent->animcache_svector3f)
7341 wanttangents = false;
7342 if (wantnormals || wanttangents)
7344 numvertices = model->surfmesh.num_vertices;
7346 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7349 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7350 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7352 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7353 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7359 // see if this ent is worth caching
7360 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7362 // get some memory for this entity and generate mesh data
7363 numvertices = model->surfmesh.num_vertices;
7364 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7366 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7369 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7370 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7372 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7373 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7378 void R_AnimCache_CacheVisibleEntities(void)
7381 qboolean wantnormals = true;
7382 qboolean wanttangents = !r_showsurfaces.integer;
7384 switch(vid.renderpath)
7386 case RENDERPATH_GL20:
7387 case RENDERPATH_D3D9:
7388 case RENDERPATH_D3D10:
7389 case RENDERPATH_D3D11:
7390 case RENDERPATH_GLES2:
7392 case RENDERPATH_GL13:
7393 case RENDERPATH_GL11:
7394 wanttangents = false;
7396 case RENDERPATH_SOFT:
7400 if (r_shownormals.integer)
7401 wanttangents = wantnormals = true;
7403 // TODO: thread this
7404 // NOTE: R_PrepareRTLights() also caches entities
7406 for (i = 0;i < r_refdef.scene.numentities;i++)
7407 if (r_refdef.viewcache.entityvisible[i])
7408 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7411 //==================================================================================
7413 static void R_View_UpdateEntityLighting (void)
7416 entity_render_t *ent;
7417 vec3_t tempdiffusenormal, avg;
7418 vec_t f, fa, fd, fdd;
7419 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7421 for (i = 0;i < r_refdef.scene.numentities;i++)
7423 ent = r_refdef.scene.entities[i];
7425 // skip unseen models
7426 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7430 if (ent->model && ent->model->brush.num_leafs)
7432 // TODO: use modellight for r_ambient settings on world?
7433 VectorSet(ent->modellight_ambient, 0, 0, 0);
7434 VectorSet(ent->modellight_diffuse, 0, 0, 0);
7435 VectorSet(ent->modellight_lightdir, 0, 0, 1);
7439 // fetch the lighting from the worldmodel data
7440 VectorClear(ent->modellight_ambient);
7441 VectorClear(ent->modellight_diffuse);
7442 VectorClear(tempdiffusenormal);
7443 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7446 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7448 // complete lightning for lit sprites
7449 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
7450 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
7452 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
7453 org[2] = org[2] + r_overheadsprites_pushback.value;
7454 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
7457 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
7459 if(ent->flags & RENDER_EQUALIZE)
7461 // first fix up ambient lighting...
7462 if(r_equalize_entities_minambient.value > 0)
7464 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7467 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7468 if(fa < r_equalize_entities_minambient.value * fd)
7471 // fa'/fd' = minambient
7472 // fa'+0.25*fd' = fa+0.25*fd
7474 // fa' = fd' * minambient
7475 // fd'*(0.25+minambient) = fa+0.25*fd
7477 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7478 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7480 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7481 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
7482 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7483 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7488 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7490 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
7491 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7495 // adjust brightness and saturation to target
7496 avg[0] = avg[1] = avg[2] = fa / f;
7497 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
7498 avg[0] = avg[1] = avg[2] = fd / f;
7499 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
7505 VectorSet(ent->modellight_ambient, 1, 1, 1);
7507 // move the light direction into modelspace coordinates for lighting code
7508 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7509 if(VectorLength2(ent->modellight_lightdir) == 0)
7510 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7511 VectorNormalize(ent->modellight_lightdir);
7515 #define MAX_LINEOFSIGHTTRACES 64
7517 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7520 vec3_t boxmins, boxmaxs;
7523 dp_model_t *model = r_refdef.scene.worldmodel;
7525 if (!model || !model->brush.TraceLineOfSight)
7528 // expand the box a little
7529 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7530 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7531 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7532 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7533 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7534 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7536 // return true if eye is inside enlarged box
7537 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7541 VectorCopy(eye, start);
7542 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7543 if (model->brush.TraceLineOfSight(model, start, end))
7546 // try various random positions
7547 for (i = 0;i < numsamples;i++)
7549 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7550 if (model->brush.TraceLineOfSight(model, start, end))
7558 static void R_View_UpdateEntityVisible (void)
7563 entity_render_t *ent;
7565 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7566 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7567 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
7568 : RENDER_EXTERIORMODEL;
7569 if (!r_drawviewmodel.integer)
7570 renderimask |= RENDER_VIEWMODEL;
7571 if (!r_drawexteriormodel.integer)
7572 renderimask |= RENDER_EXTERIORMODEL;
7573 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
7575 // worldmodel can check visibility
7576 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
7577 for (i = 0;i < r_refdef.scene.numentities;i++)
7579 ent = r_refdef.scene.entities[i];
7580 if (!(ent->flags & renderimask))
7581 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)))
7582 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))
7583 r_refdef.viewcache.entityvisible[i] = true;
7585 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
7586 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
7588 for (i = 0;i < r_refdef.scene.numentities;i++)
7590 ent = r_refdef.scene.entities[i];
7591 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
7593 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
7595 continue; // temp entities do pvs only
7596 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
7597 ent->last_trace_visibility = realtime;
7598 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
7599 r_refdef.viewcache.entityvisible[i] = 0;
7606 // no worldmodel or it can't check visibility
7607 for (i = 0;i < r_refdef.scene.numentities;i++)
7609 ent = r_refdef.scene.entities[i];
7610 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));
7615 /// only used if skyrendermasked, and normally returns false
7616 int R_DrawBrushModelsSky (void)
7619 entity_render_t *ent;
7622 for (i = 0;i < r_refdef.scene.numentities;i++)
7624 if (!r_refdef.viewcache.entityvisible[i])
7626 ent = r_refdef.scene.entities[i];
7627 if (!ent->model || !ent->model->DrawSky)
7629 ent->model->DrawSky(ent);
7635 static void R_DrawNoModel(entity_render_t *ent);
7636 static void R_DrawModels(void)
7639 entity_render_t *ent;
7641 for (i = 0;i < r_refdef.scene.numentities;i++)
7643 if (!r_refdef.viewcache.entityvisible[i])
7645 ent = r_refdef.scene.entities[i];
7646 r_refdef.stats.entities++;
7647 if (ent->model && ent->model->Draw != NULL)
7648 ent->model->Draw(ent);
7654 static void R_DrawModelsDepth(void)
7657 entity_render_t *ent;
7659 for (i = 0;i < r_refdef.scene.numentities;i++)
7661 if (!r_refdef.viewcache.entityvisible[i])
7663 ent = r_refdef.scene.entities[i];
7664 if (ent->model && ent->model->DrawDepth != NULL)
7665 ent->model->DrawDepth(ent);
7669 static void R_DrawModelsDebug(void)
7672 entity_render_t *ent;
7674 for (i = 0;i < r_refdef.scene.numentities;i++)
7676 if (!r_refdef.viewcache.entityvisible[i])
7678 ent = r_refdef.scene.entities[i];
7679 if (ent->model && ent->model->DrawDebug != NULL)
7680 ent->model->DrawDebug(ent);
7684 static void R_DrawModelsAddWaterPlanes(void)
7687 entity_render_t *ent;
7689 for (i = 0;i < r_refdef.scene.numentities;i++)
7691 if (!r_refdef.viewcache.entityvisible[i])
7693 ent = r_refdef.scene.entities[i];
7694 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
7695 ent->model->DrawAddWaterPlanes(ent);
7699 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
7701 if (r_hdr_irisadaptation.integer)
7705 vec3_t diffusenormal;
7710 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
7711 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
7712 brightness = max(0.0000001f, brightness);
7713 goal = r_hdr_irisadaptation_multiplier.value / brightness;
7714 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
7715 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
7716 current = r_hdr_irisadaptation_value.value;
7718 current = min(current + adjust, goal);
7719 else if (current > goal)
7720 current = max(current - adjust, goal);
7721 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
7722 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
7724 else if (r_hdr_irisadaptation_value.value != 1.0f)
7725 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
7728 static void R_View_SetFrustum(const int *scissor)
7731 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
7732 vec3_t forward, left, up, origin, v;
7736 // flipped x coordinates (because x points left here)
7737 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
7738 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
7740 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
7741 switch(vid.renderpath)
7743 case RENDERPATH_D3D9:
7744 case RENDERPATH_D3D10:
7745 case RENDERPATH_D3D11:
7746 case RENDERPATH_SOFT:
7747 // non-flipped y coordinates
7748 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7749 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7751 case RENDERPATH_GL11:
7752 case RENDERPATH_GL13:
7753 case RENDERPATH_GL20:
7754 case RENDERPATH_GLES2:
7755 // non-flipped y coordinates
7756 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7757 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7762 // we can't trust r_refdef.view.forward and friends in reflected scenes
7763 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
7766 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
7767 r_refdef.view.frustum[0].normal[1] = 0 - 0;
7768 r_refdef.view.frustum[0].normal[2] = -1 - 0;
7769 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
7770 r_refdef.view.frustum[1].normal[1] = 0 + 0;
7771 r_refdef.view.frustum[1].normal[2] = -1 + 0;
7772 r_refdef.view.frustum[2].normal[0] = 0 - 0;
7773 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
7774 r_refdef.view.frustum[2].normal[2] = -1 - 0;
7775 r_refdef.view.frustum[3].normal[0] = 0 + 0;
7776 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
7777 r_refdef.view.frustum[3].normal[2] = -1 + 0;
7781 zNear = r_refdef.nearclip;
7782 nudge = 1.0 - 1.0 / (1<<23);
7783 r_refdef.view.frustum[4].normal[0] = 0 - 0;
7784 r_refdef.view.frustum[4].normal[1] = 0 - 0;
7785 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7786 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
7787 r_refdef.view.frustum[5].normal[0] = 0 + 0;
7788 r_refdef.view.frustum[5].normal[1] = 0 + 0;
7789 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7790 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7796 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
7797 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
7798 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
7799 r_refdef.view.frustum[0].dist = m[15] - m[12];
7801 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
7802 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
7803 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
7804 r_refdef.view.frustum[1].dist = m[15] + m[12];
7806 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
7807 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
7808 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
7809 r_refdef.view.frustum[2].dist = m[15] - m[13];
7811 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
7812 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
7813 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
7814 r_refdef.view.frustum[3].dist = m[15] + m[13];
7816 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
7817 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
7818 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
7819 r_refdef.view.frustum[4].dist = m[15] - m[14];
7821 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
7822 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
7823 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
7824 r_refdef.view.frustum[5].dist = m[15] + m[14];
7827 if (r_refdef.view.useperspective)
7829 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
7830 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]);
7831 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]);
7832 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]);
7833 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]);
7835 // then the normals from the corners relative to origin
7836 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
7837 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
7838 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
7839 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
7841 // in a NORMAL view, forward cross left == up
7842 // in a REFLECTED view, forward cross left == down
7843 // so our cross products above need to be adjusted for a left handed coordinate system
7844 CrossProduct(forward, left, v);
7845 if(DotProduct(v, up) < 0)
7847 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
7848 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
7849 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
7850 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
7853 // Leaving those out was a mistake, those were in the old code, and they
7854 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
7855 // I couldn't reproduce it after adding those normalizations. --blub
7856 VectorNormalize(r_refdef.view.frustum[0].normal);
7857 VectorNormalize(r_refdef.view.frustum[1].normal);
7858 VectorNormalize(r_refdef.view.frustum[2].normal);
7859 VectorNormalize(r_refdef.view.frustum[3].normal);
7861 // make the corners absolute
7862 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
7863 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
7864 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
7865 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
7868 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7870 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
7871 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
7872 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
7873 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
7874 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7878 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
7879 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
7880 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
7881 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
7882 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7883 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
7884 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
7885 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
7886 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
7887 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7889 r_refdef.view.numfrustumplanes = 5;
7891 if (r_refdef.view.useclipplane)
7893 r_refdef.view.numfrustumplanes = 6;
7894 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
7897 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7898 PlaneClassify(r_refdef.view.frustum + i);
7900 // LordHavoc: note to all quake engine coders, Quake had a special case
7901 // for 90 degrees which assumed a square view (wrong), so I removed it,
7902 // Quake2 has it disabled as well.
7904 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
7905 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
7906 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
7907 //PlaneClassify(&frustum[0]);
7909 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
7910 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
7911 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
7912 //PlaneClassify(&frustum[1]);
7914 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
7915 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
7916 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
7917 //PlaneClassify(&frustum[2]);
7919 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
7920 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
7921 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
7922 //PlaneClassify(&frustum[3]);
7925 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
7926 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
7927 //PlaneClassify(&frustum[4]);
7930 void R_View_UpdateWithScissor(const int *myscissor)
7932 R_Main_ResizeViewCache();
7933 R_View_SetFrustum(myscissor);
7934 R_View_WorldVisibility(r_refdef.view.useclipplane);
7935 R_View_UpdateEntityVisible();
7936 R_View_UpdateEntityLighting();
7939 void R_View_Update(void)
7941 R_Main_ResizeViewCache();
7942 R_View_SetFrustum(NULL);
7943 R_View_WorldVisibility(r_refdef.view.useclipplane);
7944 R_View_UpdateEntityVisible();
7945 R_View_UpdateEntityLighting();
7948 void R_SetupView(qboolean allowwaterclippingplane)
7950 const float *customclipplane = NULL;
7952 if (r_refdef.view.useclipplane && allowwaterclippingplane)
7954 // LordHavoc: couldn't figure out how to make this approach the
7955 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
7956 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
7957 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
7958 dist = r_refdef.view.clipplane.dist;
7959 plane[0] = r_refdef.view.clipplane.normal[0];
7960 plane[1] = r_refdef.view.clipplane.normal[1];
7961 plane[2] = r_refdef.view.clipplane.normal[2];
7963 customclipplane = plane;
7966 if (!r_refdef.view.useperspective)
7967 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);
7968 else if (vid.stencil && r_useinfinitefarclip.integer)
7969 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);
7971 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);
7972 R_SetViewport(&r_refdef.view.viewport);
7975 void R_EntityMatrix(const matrix4x4_t *matrix)
7977 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
7979 gl_modelmatrixchanged = false;
7980 gl_modelmatrix = *matrix;
7981 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
7982 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
7983 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
7984 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
7986 switch(vid.renderpath)
7988 case RENDERPATH_D3D9:
7990 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
7991 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
7994 case RENDERPATH_D3D10:
7995 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
7997 case RENDERPATH_D3D11:
7998 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8000 case RENDERPATH_GL13:
8001 case RENDERPATH_GL11:
8002 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8004 case RENDERPATH_SOFT:
8005 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
8006 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
8008 case RENDERPATH_GL20:
8009 case RENDERPATH_GLES2:
8010 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8011 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8017 void R_ResetViewRendering2D(void)
8019 r_viewport_t viewport;
8022 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8023 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);
8024 R_SetViewport(&viewport);
8025 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8026 GL_Color(1, 1, 1, 1);
8027 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8028 GL_BlendFunc(GL_ONE, GL_ZERO);
8029 GL_ScissorTest(false);
8030 GL_DepthMask(false);
8031 GL_DepthRange(0, 1);
8032 GL_DepthTest(false);
8033 GL_DepthFunc(GL_LEQUAL);
8034 R_EntityMatrix(&identitymatrix);
8035 R_Mesh_ResetTextureState();
8036 GL_PolygonOffset(0, 0);
8037 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8038 switch(vid.renderpath)
8040 case RENDERPATH_GL11:
8041 case RENDERPATH_GL13:
8042 case RENDERPATH_GL20:
8043 case RENDERPATH_GLES2:
8044 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8046 case RENDERPATH_D3D9:
8047 case RENDERPATH_D3D10:
8048 case RENDERPATH_D3D11:
8049 case RENDERPATH_SOFT:
8052 GL_CullFace(GL_NONE);
8055 void R_ResetViewRendering3D(void)
8060 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8061 GL_Color(1, 1, 1, 1);
8062 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8063 GL_BlendFunc(GL_ONE, GL_ZERO);
8064 GL_ScissorTest(true);
8066 GL_DepthRange(0, 1);
8068 GL_DepthFunc(GL_LEQUAL);
8069 R_EntityMatrix(&identitymatrix);
8070 R_Mesh_ResetTextureState();
8071 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8072 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8073 switch(vid.renderpath)
8075 case RENDERPATH_GL11:
8076 case RENDERPATH_GL13:
8077 case RENDERPATH_GL20:
8078 case RENDERPATH_GLES2:
8079 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8081 case RENDERPATH_D3D9:
8082 case RENDERPATH_D3D10:
8083 case RENDERPATH_D3D11:
8084 case RENDERPATH_SOFT:
8087 GL_CullFace(r_refdef.view.cullface_back);
8092 R_RenderView_UpdateViewVectors
8095 static void R_RenderView_UpdateViewVectors(void)
8097 // break apart the view matrix into vectors for various purposes
8098 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8099 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8100 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8101 VectorNegate(r_refdef.view.left, r_refdef.view.right);
8102 // make an inverted copy of the view matrix for tracking sprites
8103 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8106 void R_RenderScene(void);
8107 void R_RenderWaterPlanes(void);
8109 static void R_Water_StartFrame(void)
8112 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8113 r_waterstate_waterplane_t *p;
8115 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8118 switch(vid.renderpath)
8120 case RENDERPATH_GL20:
8121 case RENDERPATH_D3D9:
8122 case RENDERPATH_D3D10:
8123 case RENDERPATH_D3D11:
8124 case RENDERPATH_SOFT:
8125 case RENDERPATH_GLES2:
8127 case RENDERPATH_GL13:
8128 case RENDERPATH_GL11:
8132 // set waterwidth and waterheight to the water resolution that will be
8133 // used (often less than the screen resolution for faster rendering)
8134 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8135 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8137 // calculate desired texture sizes
8138 // can't use water if the card does not support the texture size
8139 if (!r_water.integer || r_showsurfaces.integer)
8140 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8141 else if (vid.support.arb_texture_non_power_of_two)
8143 texturewidth = waterwidth;
8144 textureheight = waterheight;
8145 camerawidth = waterwidth;
8146 cameraheight = waterheight;
8150 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
8151 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
8152 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
8153 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
8156 // allocate textures as needed
8157 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8159 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8160 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8162 if (p->texture_refraction)
8163 R_FreeTexture(p->texture_refraction);
8164 p->texture_refraction = NULL;
8165 if (p->texture_reflection)
8166 R_FreeTexture(p->texture_reflection);
8167 p->texture_reflection = NULL;
8168 if (p->texture_camera)
8169 R_FreeTexture(p->texture_camera);
8170 p->texture_camera = NULL;
8172 memset(&r_waterstate, 0, sizeof(r_waterstate));
8173 r_waterstate.texturewidth = texturewidth;
8174 r_waterstate.textureheight = textureheight;
8175 r_waterstate.camerawidth = camerawidth;
8176 r_waterstate.cameraheight = cameraheight;
8179 if (r_waterstate.texturewidth)
8181 r_waterstate.enabled = true;
8183 // when doing a reduced render (HDR) we want to use a smaller area
8184 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8185 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8187 // set up variables that will be used in shader setup
8188 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8189 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8190 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8191 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8194 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8195 r_waterstate.numwaterplanes = 0;
8198 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8200 int triangleindex, planeindex;
8206 r_waterstate_waterplane_t *p;
8207 texture_t *t = R_GetCurrentTexture(surface->texture);
8209 // just use the first triangle with a valid normal for any decisions
8210 VectorClear(normal);
8211 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8213 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8214 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8215 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8216 TriangleNormal(vert[0], vert[1], vert[2], normal);
8217 if (VectorLength2(normal) >= 0.001)
8221 VectorCopy(normal, plane.normal);
8222 VectorNormalize(plane.normal);
8223 plane.dist = DotProduct(vert[0], plane.normal);
8224 PlaneClassify(&plane);
8225 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8227 // skip backfaces (except if nocullface is set)
8228 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8230 VectorNegate(plane.normal, plane.normal);
8232 PlaneClassify(&plane);
8236 // find a matching plane if there is one
8237 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8238 if(p->camera_entity == t->camera_entity)
8239 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8241 if (planeindex >= r_waterstate.maxwaterplanes)
8242 return; // nothing we can do, out of planes
8244 // if this triangle does not fit any known plane rendered this frame, add one
8245 if (planeindex >= r_waterstate.numwaterplanes)
8247 // store the new plane
8248 r_waterstate.numwaterplanes++;
8250 // clear materialflags and pvs
8251 p->materialflags = 0;
8252 p->pvsvalid = false;
8253 p->camera_entity = t->camera_entity;
8254 VectorCopy(surface->mins, p->mins);
8255 VectorCopy(surface->maxs, p->maxs);
8260 p->mins[0] = min(p->mins[0], surface->mins[0]);
8261 p->mins[1] = min(p->mins[1], surface->mins[1]);
8262 p->mins[2] = min(p->mins[2], surface->mins[2]);
8263 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8264 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8265 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8267 // merge this surface's materialflags into the waterplane
8268 p->materialflags |= t->currentmaterialflags;
8269 if(!(p->materialflags & MATERIALFLAG_CAMERA))
8271 // merge this surface's PVS into the waterplane
8272 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8273 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8274 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8276 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8282 static void R_Water_ProcessPlanes(void)
8285 r_refdef_view_t originalview;
8286 r_refdef_view_t myview;
8288 r_waterstate_waterplane_t *p;
8291 originalview = r_refdef.view;
8293 // make sure enough textures are allocated
8294 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8296 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8298 if (!p->texture_refraction)
8299 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);
8300 if (!p->texture_refraction)
8303 else if (p->materialflags & MATERIALFLAG_CAMERA)
8305 if (!p->texture_camera)
8306 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);
8307 if (!p->texture_camera)
8311 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8313 if (!p->texture_reflection)
8314 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);
8315 if (!p->texture_reflection)
8321 r_refdef.view = originalview;
8322 r_refdef.view.showdebug = false;
8323 r_refdef.view.width = r_waterstate.waterwidth;
8324 r_refdef.view.height = r_waterstate.waterheight;
8325 r_refdef.view.useclipplane = true;
8326 myview = r_refdef.view;
8327 r_waterstate.renderingscene = true;
8328 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8330 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8332 r_refdef.view = myview;
8333 if(r_water_scissormode.integer)
8336 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8337 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8340 // render reflected scene and copy into texture
8341 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8342 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8343 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8344 r_refdef.view.clipplane = p->plane;
8346 // reverse the cullface settings for this render
8347 r_refdef.view.cullface_front = GL_FRONT;
8348 r_refdef.view.cullface_back = GL_BACK;
8349 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8351 r_refdef.view.usecustompvs = true;
8353 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8355 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8358 R_ResetViewRendering3D();
8359 R_ClearScreen(r_refdef.fogenabled);
8360 if(r_water_scissormode.integer & 2)
8361 R_View_UpdateWithScissor(myscissor);
8364 if(r_water_scissormode.integer & 1)
8365 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8368 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);
8371 // render the normal view scene and copy into texture
8372 // (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)
8373 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8375 r_refdef.view = myview;
8376 if(r_water_scissormode.integer)
8379 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8380 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8383 r_waterstate.renderingrefraction = true;
8385 r_refdef.view.clipplane = p->plane;
8386 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8387 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8389 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8391 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8392 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8393 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8394 R_RenderView_UpdateViewVectors();
8395 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8397 r_refdef.view.usecustompvs = true;
8398 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);
8402 PlaneClassify(&r_refdef.view.clipplane);
8404 R_ResetViewRendering3D();
8405 R_ClearScreen(r_refdef.fogenabled);
8406 if(r_water_scissormode.integer & 2)
8407 R_View_UpdateWithScissor(myscissor);
8410 if(r_water_scissormode.integer & 1)
8411 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8414 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);
8415 r_waterstate.renderingrefraction = false;
8417 else if (p->materialflags & MATERIALFLAG_CAMERA)
8419 r_refdef.view = myview;
8421 r_refdef.view.clipplane = p->plane;
8422 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8423 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8425 r_refdef.view.width = r_waterstate.camerawidth;
8426 r_refdef.view.height = r_waterstate.cameraheight;
8427 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8428 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8430 if(p->camera_entity)
8432 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8433 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8436 // note: all of the view is used for displaying... so
8437 // there is no use in scissoring
8439 // reverse the cullface settings for this render
8440 r_refdef.view.cullface_front = GL_FRONT;
8441 r_refdef.view.cullface_back = GL_BACK;
8442 // also reverse the view matrix
8443 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
8444 R_RenderView_UpdateViewVectors();
8445 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8447 r_refdef.view.usecustompvs = true;
8448 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);
8451 // camera needs no clipplane
8452 r_refdef.view.useclipplane = false;
8454 PlaneClassify(&r_refdef.view.clipplane);
8456 R_ResetViewRendering3D();
8457 R_ClearScreen(r_refdef.fogenabled);
8461 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);
8462 r_waterstate.renderingrefraction = false;
8466 r_waterstate.renderingscene = false;
8467 r_refdef.view = originalview;
8468 R_ResetViewRendering3D();
8469 R_ClearScreen(r_refdef.fogenabled);
8473 r_refdef.view = originalview;
8474 r_waterstate.renderingscene = false;
8475 Cvar_SetValueQuick(&r_water, 0);
8476 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
8480 void R_Bloom_StartFrame(void)
8482 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8484 switch(vid.renderpath)
8486 case RENDERPATH_GL20:
8487 case RENDERPATH_D3D9:
8488 case RENDERPATH_D3D10:
8489 case RENDERPATH_D3D11:
8490 case RENDERPATH_SOFT:
8491 case RENDERPATH_GLES2:
8493 case RENDERPATH_GL13:
8494 case RENDERPATH_GL11:
8498 // set bloomwidth and bloomheight to the bloom resolution that will be
8499 // used (often less than the screen resolution for faster rendering)
8500 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8501 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8502 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8503 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8504 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8506 // calculate desired texture sizes
8507 if (vid.support.arb_texture_non_power_of_two)
8509 screentexturewidth = r_refdef.view.width;
8510 screentextureheight = r_refdef.view.height;
8511 bloomtexturewidth = r_bloomstate.bloomwidth;
8512 bloomtextureheight = r_bloomstate.bloomheight;
8516 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
8517 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
8518 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
8519 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
8522 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))
8524 Cvar_SetValueQuick(&r_hdr, 0);
8525 Cvar_SetValueQuick(&r_bloom, 0);
8526 Cvar_SetValueQuick(&r_motionblur, 0);
8527 Cvar_SetValueQuick(&r_damageblur, 0);
8530 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)))
8531 screentexturewidth = screentextureheight = 0;
8532 if (!r_hdr.integer && !r_bloom.integer)
8533 bloomtexturewidth = bloomtextureheight = 0;
8535 // allocate textures as needed
8536 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8538 if (r_bloomstate.texture_screen)
8539 R_FreeTexture(r_bloomstate.texture_screen);
8540 r_bloomstate.texture_screen = NULL;
8541 r_bloomstate.screentexturewidth = screentexturewidth;
8542 r_bloomstate.screentextureheight = screentextureheight;
8543 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8544 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);
8546 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8548 if (r_bloomstate.texture_bloom)
8549 R_FreeTexture(r_bloomstate.texture_bloom);
8550 r_bloomstate.texture_bloom = NULL;
8551 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8552 r_bloomstate.bloomtextureheight = bloomtextureheight;
8553 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8554 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);
8557 // when doing a reduced render (HDR) we want to use a smaller area
8558 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8559 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8560 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8561 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8562 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8564 // set up a texcoord array for the full resolution screen image
8565 // (we have to keep this around to copy back during final render)
8566 r_bloomstate.screentexcoord2f[0] = 0;
8567 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
8568 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
8569 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
8570 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
8571 r_bloomstate.screentexcoord2f[5] = 0;
8572 r_bloomstate.screentexcoord2f[6] = 0;
8573 r_bloomstate.screentexcoord2f[7] = 0;
8575 // set up a texcoord array for the reduced resolution bloom image
8576 // (which will be additive blended over the screen image)
8577 r_bloomstate.bloomtexcoord2f[0] = 0;
8578 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8579 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8580 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8581 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8582 r_bloomstate.bloomtexcoord2f[5] = 0;
8583 r_bloomstate.bloomtexcoord2f[6] = 0;
8584 r_bloomstate.bloomtexcoord2f[7] = 0;
8586 switch(vid.renderpath)
8588 case RENDERPATH_GL11:
8589 case RENDERPATH_GL13:
8590 case RENDERPATH_GL20:
8591 case RENDERPATH_SOFT:
8592 case RENDERPATH_GLES2:
8594 case RENDERPATH_D3D9:
8595 case RENDERPATH_D3D10:
8596 case RENDERPATH_D3D11:
8599 for (i = 0;i < 4;i++)
8601 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
8602 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
8603 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
8604 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
8610 if (r_hdr.integer || r_bloom.integer)
8612 r_bloomstate.enabled = true;
8613 r_bloomstate.hdr = r_hdr.integer != 0;
8616 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);
8619 void R_Bloom_CopyBloomTexture(float colorscale)
8621 r_refdef.stats.bloom++;
8623 // scale down screen texture to the bloom texture size
8625 R_SetViewport(&r_bloomstate.viewport);
8626 GL_BlendFunc(GL_ONE, GL_ZERO);
8627 GL_Color(colorscale, colorscale, colorscale, 1);
8628 // 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...
8629 switch(vid.renderpath)
8631 case RENDERPATH_GL11:
8632 case RENDERPATH_GL13:
8633 case RENDERPATH_GL20:
8634 case RENDERPATH_SOFT:
8635 case RENDERPATH_GLES2:
8636 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8638 case RENDERPATH_D3D9:
8639 case RENDERPATH_D3D10:
8640 case RENDERPATH_D3D11:
8641 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8644 // TODO: do boxfilter scale-down in shader?
8645 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8646 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8647 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8649 // we now have a bloom image in the framebuffer
8650 // copy it into the bloom image texture for later processing
8651 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);
8652 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8655 void R_Bloom_CopyHDRTexture(void)
8657 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);
8658 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8661 void R_Bloom_MakeTexture(void)
8664 float xoffset, yoffset, r, brighten;
8666 r_refdef.stats.bloom++;
8668 R_ResetViewRendering2D();
8670 // we have a bloom image in the framebuffer
8672 R_SetViewport(&r_bloomstate.viewport);
8674 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
8677 r = bound(0, r_bloom_colorexponent.value / x, 1);
8678 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
8680 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
8681 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8682 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8683 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8685 // copy the vertically blurred bloom view to a texture
8686 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);
8687 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8690 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
8691 brighten = r_bloom_brighten.value;
8693 brighten *= r_hdr_range.value;
8694 brighten = sqrt(brighten);
8696 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
8697 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8699 for (dir = 0;dir < 2;dir++)
8701 // blend on at multiple vertical offsets to achieve a vertical blur
8702 // TODO: do offset blends using GLSL
8703 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
8704 GL_BlendFunc(GL_ONE, GL_ZERO);
8705 for (x = -range;x <= range;x++)
8707 if (!dir){xoffset = 0;yoffset = x;}
8708 else {xoffset = x;yoffset = 0;}
8709 xoffset /= (float)r_bloomstate.bloomtexturewidth;
8710 yoffset /= (float)r_bloomstate.bloomtextureheight;
8711 // compute a texcoord array with the specified x and y offset
8712 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
8713 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8714 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8715 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8716 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8717 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
8718 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
8719 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
8720 // this r value looks like a 'dot' particle, fading sharply to
8721 // black at the edges
8722 // (probably not realistic but looks good enough)
8723 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
8724 //r = brighten/(range*2+1);
8725 r = brighten / (range * 2 + 1);
8727 r *= (1 - x*x/(float)(range*range));
8728 GL_Color(r, r, r, 1);
8729 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
8730 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8731 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8732 GL_BlendFunc(GL_ONE, GL_ONE);
8735 // copy the vertically blurred bloom view to a texture
8736 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);
8737 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8741 void R_HDR_RenderBloomTexture(void)
8743 int oldwidth, oldheight;
8744 float oldcolorscale;
8745 qboolean oldwaterstate;
8747 oldwaterstate = r_waterstate.enabled;
8748 oldcolorscale = r_refdef.view.colorscale;
8749 oldwidth = r_refdef.view.width;
8750 oldheight = r_refdef.view.height;
8751 r_refdef.view.width = r_bloomstate.bloomwidth;
8752 r_refdef.view.height = r_bloomstate.bloomheight;
8754 if(r_hdr.integer < 2)
8755 r_waterstate.enabled = false;
8757 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
8758 // TODO: add exposure compensation features
8759 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
8761 r_refdef.view.showdebug = false;
8762 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
8764 R_ResetViewRendering3D();
8766 R_ClearScreen(r_refdef.fogenabled);
8767 if (r_timereport_active)
8768 R_TimeReport("HDRclear");
8771 if (r_timereport_active)
8772 R_TimeReport("visibility");
8774 // only do secondary renders with HDR if r_hdr is 2 or higher
8775 r_waterstate.numwaterplanes = 0;
8776 if (r_waterstate.enabled)
8777 R_RenderWaterPlanes();
8779 r_refdef.view.showdebug = true;
8781 r_waterstate.numwaterplanes = 0;
8783 R_ResetViewRendering2D();
8785 R_Bloom_CopyHDRTexture();
8786 R_Bloom_MakeTexture();
8788 // restore the view settings
8789 r_waterstate.enabled = oldwaterstate;
8790 r_refdef.view.width = oldwidth;
8791 r_refdef.view.height = oldheight;
8792 r_refdef.view.colorscale = oldcolorscale;
8794 R_ResetViewRendering3D();
8796 R_ClearScreen(r_refdef.fogenabled);
8797 if (r_timereport_active)
8798 R_TimeReport("viewclear");
8801 static void R_BlendView(void)
8803 unsigned int permutation;
8804 float uservecs[4][4];
8806 switch (vid.renderpath)
8808 case RENDERPATH_GL20:
8809 case RENDERPATH_D3D9:
8810 case RENDERPATH_D3D10:
8811 case RENDERPATH_D3D11:
8812 case RENDERPATH_SOFT:
8813 case RENDERPATH_GLES2:
8815 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
8816 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
8817 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
8818 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
8819 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
8821 if (r_bloomstate.texture_screen)
8823 // make sure the buffer is available
8824 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
8826 R_ResetViewRendering2D();
8828 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
8830 // declare variables
8832 static float avgspeed;
8834 speed = VectorLength(cl.movement_velocity);
8836 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
8837 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
8839 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
8840 speed = bound(0, speed, 1);
8841 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
8843 // calculate values into a standard alpha
8844 cl.motionbluralpha = 1 - exp(-
8846 (r_motionblur.value * speed / 80)
8848 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
8851 max(0.0001, cl.time - cl.oldtime) // fps independent
8854 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
8855 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
8857 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
8859 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8860 GL_Color(1, 1, 1, cl.motionbluralpha);
8861 switch(vid.renderpath)
8863 case RENDERPATH_GL11:
8864 case RENDERPATH_GL13:
8865 case RENDERPATH_GL20:
8866 case RENDERPATH_SOFT:
8867 case RENDERPATH_GLES2:
8868 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8870 case RENDERPATH_D3D9:
8871 case RENDERPATH_D3D10:
8872 case RENDERPATH_D3D11:
8873 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8876 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8877 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8878 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8882 // copy view into the screen texture
8883 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);
8884 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8886 else if (!r_bloomstate.texture_bloom)
8888 // we may still have to do view tint...
8889 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8891 // apply a color tint to the whole view
8892 R_ResetViewRendering2D();
8893 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8894 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
8895 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8896 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8897 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8899 break; // no screen processing, no bloom, skip it
8902 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
8904 // render simple bloom effect
8905 // copy the screen and shrink it and darken it for the bloom process
8906 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
8907 // make the bloom texture
8908 R_Bloom_MakeTexture();
8911 #if _MSC_VER >= 1400
8912 #define sscanf sscanf_s
8914 memset(uservecs, 0, sizeof(uservecs));
8915 if (r_glsl_postprocess_uservec1_enable.integer)
8916 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
8917 if (r_glsl_postprocess_uservec2_enable.integer)
8918 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
8919 if (r_glsl_postprocess_uservec3_enable.integer)
8920 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
8921 if (r_glsl_postprocess_uservec4_enable.integer)
8922 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
8924 R_ResetViewRendering2D();
8925 GL_Color(1, 1, 1, 1);
8926 GL_BlendFunc(GL_ONE, GL_ZERO);
8928 switch(vid.renderpath)
8930 case RENDERPATH_GL20:
8931 case RENDERPATH_GLES2:
8932 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8933 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
8934 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
8935 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
8936 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
8937 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]);
8938 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8939 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]);
8940 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]);
8941 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]);
8942 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]);
8943 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
8944 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8945 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);
8947 case RENDERPATH_D3D9:
8949 // 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...
8950 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8951 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
8952 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
8953 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
8954 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
8955 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8956 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8957 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
8958 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
8959 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
8960 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
8961 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
8962 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
8963 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
8966 case RENDERPATH_D3D10:
8967 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
8969 case RENDERPATH_D3D11:
8970 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
8972 case RENDERPATH_SOFT:
8973 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8974 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
8975 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
8976 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
8977 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
8978 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8979 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8980 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
8981 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
8982 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
8983 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
8984 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
8985 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8986 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
8991 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8992 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8994 case RENDERPATH_GL13:
8995 case RENDERPATH_GL11:
8996 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8998 // apply a color tint to the whole view
8999 R_ResetViewRendering2D();
9000 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9001 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9002 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9003 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9004 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9010 matrix4x4_t r_waterscrollmatrix;
9012 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9014 if (r_refdef.fog_density)
9016 r_refdef.fogcolor[0] = r_refdef.fog_red;
9017 r_refdef.fogcolor[1] = r_refdef.fog_green;
9018 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9020 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9021 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9022 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9023 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9027 VectorCopy(r_refdef.fogcolor, fogvec);
9028 // color.rgb *= ContrastBoost * SceneBrightness;
9029 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9030 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9031 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9032 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9037 void R_UpdateVariables(void)
9041 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9043 r_refdef.farclip = r_farclip_base.value;
9044 if (r_refdef.scene.worldmodel)
9045 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9046 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9048 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9049 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9050 r_refdef.polygonfactor = 0;
9051 r_refdef.polygonoffset = 0;
9052 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9053 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9055 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9056 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9057 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
9058 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9059 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9060 if (FAKELIGHT_ENABLED)
9062 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
9064 if (r_showsurfaces.integer)
9066 r_refdef.scene.rtworld = false;
9067 r_refdef.scene.rtworldshadows = false;
9068 r_refdef.scene.rtdlight = false;
9069 r_refdef.scene.rtdlightshadows = false;
9070 r_refdef.lightmapintensity = 0;
9073 if (gamemode == GAME_NEHAHRA)
9075 if (gl_fogenable.integer)
9077 r_refdef.oldgl_fogenable = true;
9078 r_refdef.fog_density = gl_fogdensity.value;
9079 r_refdef.fog_red = gl_fogred.value;
9080 r_refdef.fog_green = gl_foggreen.value;
9081 r_refdef.fog_blue = gl_fogblue.value;
9082 r_refdef.fog_alpha = 1;
9083 r_refdef.fog_start = 0;
9084 r_refdef.fog_end = gl_skyclip.value;
9085 r_refdef.fog_height = 1<<30;
9086 r_refdef.fog_fadedepth = 128;
9088 else if (r_refdef.oldgl_fogenable)
9090 r_refdef.oldgl_fogenable = false;
9091 r_refdef.fog_density = 0;
9092 r_refdef.fog_red = 0;
9093 r_refdef.fog_green = 0;
9094 r_refdef.fog_blue = 0;
9095 r_refdef.fog_alpha = 0;
9096 r_refdef.fog_start = 0;
9097 r_refdef.fog_end = 0;
9098 r_refdef.fog_height = 1<<30;
9099 r_refdef.fog_fadedepth = 128;
9103 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9104 r_refdef.fog_start = max(0, r_refdef.fog_start);
9105 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9107 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9109 if (r_refdef.fog_density && r_drawfog.integer)
9111 r_refdef.fogenabled = true;
9112 // this is the point where the fog reaches 0.9986 alpha, which we
9113 // consider a good enough cutoff point for the texture
9114 // (0.9986 * 256 == 255.6)
9115 if (r_fog_exp2.integer)
9116 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9118 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9119 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9120 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9121 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9122 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9123 R_BuildFogHeightTexture();
9124 // fog color was already set
9125 // update the fog texture
9126 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)
9127 R_BuildFogTexture();
9128 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9129 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9132 r_refdef.fogenabled = false;
9134 switch(vid.renderpath)
9136 case RENDERPATH_GL20:
9137 case RENDERPATH_D3D9:
9138 case RENDERPATH_D3D10:
9139 case RENDERPATH_D3D11:
9140 case RENDERPATH_SOFT:
9141 case RENDERPATH_GLES2:
9142 if(v_glslgamma.integer && !vid_gammatables_trivial)
9144 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9146 // build GLSL gamma texture
9147 #define RAMPWIDTH 256
9148 unsigned short ramp[RAMPWIDTH * 3];
9149 unsigned char rampbgr[RAMPWIDTH][4];
9152 r_texture_gammaramps_serial = vid_gammatables_serial;
9154 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9155 for(i = 0; i < RAMPWIDTH; ++i)
9157 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9158 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9159 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9162 if (r_texture_gammaramps)
9164 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
9168 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9174 // remove GLSL gamma texture
9177 case RENDERPATH_GL13:
9178 case RENDERPATH_GL11:
9183 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9184 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9190 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9191 if( scenetype != r_currentscenetype ) {
9192 // store the old scenetype
9193 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9194 r_currentscenetype = scenetype;
9195 // move in the new scene
9196 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9205 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9207 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9208 if( scenetype == r_currentscenetype ) {
9209 return &r_refdef.scene;
9211 return &r_scenes_store[ scenetype ];
9220 int dpsoftrast_test;
9221 void R_RenderView(void)
9223 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
9225 dpsoftrast_test = r_test.integer;
9227 if (r_timereport_active)
9228 R_TimeReport("start");
9229 r_textureframe++; // used only by R_GetCurrentTexture
9230 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9232 if(R_CompileShader_CheckStaticParms())
9235 if (!r_drawentities.integer)
9236 r_refdef.scene.numentities = 0;
9238 R_AnimCache_ClearCache();
9239 R_FrameData_NewFrame();
9241 /* adjust for stereo display */
9242 if(R_Stereo_Active())
9244 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);
9245 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
9248 if (r_refdef.view.isoverlay)
9250 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9251 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9252 R_TimeReport("depthclear");
9254 r_refdef.view.showdebug = false;
9256 r_waterstate.enabled = false;
9257 r_waterstate.numwaterplanes = 0;
9261 r_refdef.view.matrix = originalmatrix;
9267 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9269 r_refdef.view.matrix = originalmatrix;
9270 return; //Host_Error ("R_RenderView: NULL worldmodel");
9273 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
9275 R_RenderView_UpdateViewVectors();
9277 R_Shadow_UpdateWorldLightSelection();
9279 R_Bloom_StartFrame();
9280 R_Water_StartFrame();
9283 if (r_timereport_active)
9284 R_TimeReport("viewsetup");
9286 R_ResetViewRendering3D();
9288 if (r_refdef.view.clear || r_refdef.fogenabled)
9290 R_ClearScreen(r_refdef.fogenabled);
9291 if (r_timereport_active)
9292 R_TimeReport("viewclear");
9294 r_refdef.view.clear = true;
9296 // this produces a bloom texture to be used in R_BlendView() later
9297 if (r_hdr.integer && r_bloomstate.bloomwidth)
9299 R_HDR_RenderBloomTexture();
9300 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9301 r_textureframe++; // used only by R_GetCurrentTexture
9304 r_refdef.view.showdebug = true;
9307 if (r_timereport_active)
9308 R_TimeReport("visibility");
9310 r_waterstate.numwaterplanes = 0;
9311 if (r_waterstate.enabled)
9312 R_RenderWaterPlanes();
9315 r_waterstate.numwaterplanes = 0;
9318 if (r_timereport_active)
9319 R_TimeReport("blendview");
9321 GL_Scissor(0, 0, vid.width, vid.height);
9322 GL_ScissorTest(false);
9324 r_refdef.view.matrix = originalmatrix;
9329 void R_RenderWaterPlanes(void)
9331 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9333 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9334 if (r_timereport_active)
9335 R_TimeReport("waterworld");
9338 // don't let sound skip if going slow
9339 if (r_refdef.scene.extraupdate)
9342 R_DrawModelsAddWaterPlanes();
9343 if (r_timereport_active)
9344 R_TimeReport("watermodels");
9346 if (r_waterstate.numwaterplanes)
9348 R_Water_ProcessPlanes();
9349 if (r_timereport_active)
9350 R_TimeReport("waterscenes");
9354 extern void R_DrawLightningBeams (void);
9355 extern void VM_CL_AddPolygonsToMeshQueue (void);
9356 extern void R_DrawPortals (void);
9357 extern cvar_t cl_locs_show;
9358 static void R_DrawLocs(void);
9359 static void R_DrawEntityBBoxes(void);
9360 static void R_DrawModelDecals(void);
9361 extern void R_DrawModelShadows(void);
9362 extern void R_DrawModelShadowMaps(void);
9363 extern cvar_t cl_decals_newsystem;
9364 extern qboolean r_shadow_usingdeferredprepass;
9365 void R_RenderScene(void)
9367 qboolean shadowmapping = false;
9369 if (r_timereport_active)
9370 R_TimeReport("beginscene");
9372 r_refdef.stats.renders++;
9376 // don't let sound skip if going slow
9377 if (r_refdef.scene.extraupdate)
9380 R_MeshQueue_BeginScene();
9384 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);
9386 if (r_timereport_active)
9387 R_TimeReport("skystartframe");
9389 if (cl.csqc_vidvars.drawworld)
9391 // don't let sound skip if going slow
9392 if (r_refdef.scene.extraupdate)
9395 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9397 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9398 if (r_timereport_active)
9399 R_TimeReport("worldsky");
9402 if (R_DrawBrushModelsSky() && r_timereport_active)
9403 R_TimeReport("bmodelsky");
9405 if (skyrendermasked && skyrenderlater)
9407 // we have to force off the water clipping plane while rendering sky
9411 if (r_timereport_active)
9412 R_TimeReport("sky");
9416 R_AnimCache_CacheVisibleEntities();
9417 if (r_timereport_active)
9418 R_TimeReport("animation");
9420 R_Shadow_PrepareLights();
9421 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9422 R_Shadow_PrepareModelShadows();
9423 if (r_timereport_active)
9424 R_TimeReport("preparelights");
9426 if (R_Shadow_ShadowMappingEnabled())
9427 shadowmapping = true;
9429 if (r_shadow_usingdeferredprepass)
9430 R_Shadow_DrawPrepass();
9432 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9434 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9435 if (r_timereport_active)
9436 R_TimeReport("worlddepth");
9438 if (r_depthfirst.integer >= 2)
9440 R_DrawModelsDepth();
9441 if (r_timereport_active)
9442 R_TimeReport("modeldepth");
9445 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9447 R_DrawModelShadowMaps();
9448 R_ResetViewRendering3D();
9449 // don't let sound skip if going slow
9450 if (r_refdef.scene.extraupdate)
9454 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9456 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9457 if (r_timereport_active)
9458 R_TimeReport("world");
9461 // don't let sound skip if going slow
9462 if (r_refdef.scene.extraupdate)
9466 if (r_timereport_active)
9467 R_TimeReport("models");
9469 // don't let sound skip if going slow
9470 if (r_refdef.scene.extraupdate)
9473 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9475 R_DrawModelShadows();
9476 R_ResetViewRendering3D();
9477 // don't let sound skip if going slow
9478 if (r_refdef.scene.extraupdate)
9482 if (!r_shadow_usingdeferredprepass)
9484 R_Shadow_DrawLights();
9485 if (r_timereport_active)
9486 R_TimeReport("rtlights");
9489 // don't let sound skip if going slow
9490 if (r_refdef.scene.extraupdate)
9493 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9495 R_DrawModelShadows();
9496 R_ResetViewRendering3D();
9497 // don't let sound skip if going slow
9498 if (r_refdef.scene.extraupdate)
9502 if (cl.csqc_vidvars.drawworld)
9504 if (cl_decals_newsystem.integer)
9506 R_DrawModelDecals();
9507 if (r_timereport_active)
9508 R_TimeReport("modeldecals");
9513 if (r_timereport_active)
9514 R_TimeReport("decals");
9518 if (r_timereport_active)
9519 R_TimeReport("particles");
9522 if (r_timereport_active)
9523 R_TimeReport("explosions");
9525 R_DrawLightningBeams();
9526 if (r_timereport_active)
9527 R_TimeReport("lightning");
9530 VM_CL_AddPolygonsToMeshQueue();
9532 if (r_refdef.view.showdebug)
9534 if (cl_locs_show.integer)
9537 if (r_timereport_active)
9538 R_TimeReport("showlocs");
9541 if (r_drawportals.integer)
9544 if (r_timereport_active)
9545 R_TimeReport("portals");
9548 if (r_showbboxes.value > 0)
9550 R_DrawEntityBBoxes();
9551 if (r_timereport_active)
9552 R_TimeReport("bboxes");
9556 R_MeshQueue_RenderTransparent();
9557 if (r_timereport_active)
9558 R_TimeReport("drawtrans");
9560 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))
9562 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9563 if (r_timereport_active)
9564 R_TimeReport("worlddebug");
9565 R_DrawModelsDebug();
9566 if (r_timereport_active)
9567 R_TimeReport("modeldebug");
9570 if (cl.csqc_vidvars.drawworld)
9572 R_Shadow_DrawCoronas();
9573 if (r_timereport_active)
9574 R_TimeReport("coronas");
9579 GL_DepthTest(false);
9580 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9581 GL_Color(1, 1, 1, 1);
9582 qglBegin(GL_POLYGON);
9583 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
9584 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
9585 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
9586 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
9588 qglBegin(GL_POLYGON);
9589 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]);
9590 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]);
9591 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]);
9592 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]);
9594 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9598 // don't let sound skip if going slow
9599 if (r_refdef.scene.extraupdate)
9602 R_ResetViewRendering2D();
9605 static const unsigned short bboxelements[36] =
9615 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9618 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9620 RSurf_ActiveWorldEntity();
9622 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9623 GL_DepthMask(false);
9624 GL_DepthRange(0, 1);
9625 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9626 // R_Mesh_ResetTextureState();
9628 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9629 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9630 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9631 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9632 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9633 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9634 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9635 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9636 R_FillColors(color4f, 8, cr, cg, cb, ca);
9637 if (r_refdef.fogenabled)
9639 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9641 f1 = RSurf_FogVertex(v);
9643 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9644 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9645 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9648 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
9649 R_Mesh_ResetTextureState();
9650 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9651 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
9654 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9658 prvm_edict_t *edict;
9659 prvm_prog_t *prog_save = prog;
9661 // this function draws bounding boxes of server entities
9665 GL_CullFace(GL_NONE);
9666 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9670 for (i = 0;i < numsurfaces;i++)
9672 edict = PRVM_EDICT_NUM(surfacelist[i]);
9673 switch ((int)edict->fields.server->solid)
9675 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
9676 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
9677 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
9678 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9679 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
9680 default: Vector4Set(color, 0, 0, 0, 0.50);break;
9682 color[3] *= r_showbboxes.value;
9683 color[3] = bound(0, color[3], 1);
9684 GL_DepthTest(!r_showdisabledepthtest.integer);
9685 GL_CullFace(r_refdef.view.cullface_front);
9686 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
9692 static void R_DrawEntityBBoxes(void)
9695 prvm_edict_t *edict;
9697 prvm_prog_t *prog_save = prog;
9699 // this function draws bounding boxes of server entities
9705 for (i = 0;i < prog->num_edicts;i++)
9707 edict = PRVM_EDICT_NUM(i);
9708 if (edict->priv.server->free)
9710 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
9711 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
9713 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
9715 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
9716 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
9722 static const int nomodelelement3i[24] =
9734 static const unsigned short nomodelelement3s[24] =
9746 static const float nomodelvertex3f[6*3] =
9756 static const float nomodelcolor4f[6*4] =
9758 0.0f, 0.0f, 0.5f, 1.0f,
9759 0.0f, 0.0f, 0.5f, 1.0f,
9760 0.0f, 0.5f, 0.0f, 1.0f,
9761 0.0f, 0.5f, 0.0f, 1.0f,
9762 0.5f, 0.0f, 0.0f, 1.0f,
9763 0.5f, 0.0f, 0.0f, 1.0f
9766 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9772 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);
9774 // this is only called once per entity so numsurfaces is always 1, and
9775 // surfacelist is always {0}, so this code does not handle batches
9777 if (rsurface.ent_flags & RENDER_ADDITIVE)
9779 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
9780 GL_DepthMask(false);
9782 else if (rsurface.colormod[3] < 1)
9784 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9785 GL_DepthMask(false);
9789 GL_BlendFunc(GL_ONE, GL_ZERO);
9792 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
9793 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
9794 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
9795 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
9796 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
9797 for (i = 0, c = color4f;i < 6;i++, c += 4)
9799 c[0] *= rsurface.colormod[0];
9800 c[1] *= rsurface.colormod[1];
9801 c[2] *= rsurface.colormod[2];
9802 c[3] *= rsurface.colormod[3];
9804 if (r_refdef.fogenabled)
9806 for (i = 0, c = color4f;i < 6;i++, c += 4)
9808 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
9810 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
9811 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
9812 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
9815 // R_Mesh_ResetTextureState();
9816 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9817 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
9818 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
9821 void R_DrawNoModel(entity_render_t *ent)
9824 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
9825 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
9826 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
9828 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
9831 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
9833 vec3_t right1, right2, diff, normal;
9835 VectorSubtract (org2, org1, normal);
9837 // calculate 'right' vector for start
9838 VectorSubtract (r_refdef.view.origin, org1, diff);
9839 CrossProduct (normal, diff, right1);
9840 VectorNormalize (right1);
9842 // calculate 'right' vector for end
9843 VectorSubtract (r_refdef.view.origin, org2, diff);
9844 CrossProduct (normal, diff, right2);
9845 VectorNormalize (right2);
9847 vert[ 0] = org1[0] + width * right1[0];
9848 vert[ 1] = org1[1] + width * right1[1];
9849 vert[ 2] = org1[2] + width * right1[2];
9850 vert[ 3] = org1[0] - width * right1[0];
9851 vert[ 4] = org1[1] - width * right1[1];
9852 vert[ 5] = org1[2] - width * right1[2];
9853 vert[ 6] = org2[0] - width * right2[0];
9854 vert[ 7] = org2[1] - width * right2[1];
9855 vert[ 8] = org2[2] - width * right2[2];
9856 vert[ 9] = org2[0] + width * right2[0];
9857 vert[10] = org2[1] + width * right2[1];
9858 vert[11] = org2[2] + width * right2[2];
9861 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)
9863 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
9864 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
9865 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
9866 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
9867 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
9868 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
9869 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
9870 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
9871 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
9872 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
9873 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
9874 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
9877 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
9882 VectorSet(v, x, y, z);
9883 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
9884 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
9886 if (i == mesh->numvertices)
9888 if (mesh->numvertices < mesh->maxvertices)
9890 VectorCopy(v, vertex3f);
9891 mesh->numvertices++;
9893 return mesh->numvertices;
9899 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
9903 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9904 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9905 e = mesh->element3i + mesh->numtriangles * 3;
9906 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
9908 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
9909 if (mesh->numtriangles < mesh->maxtriangles)
9914 mesh->numtriangles++;
9916 element[1] = element[2];
9920 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
9924 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9925 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9926 e = mesh->element3i + mesh->numtriangles * 3;
9927 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
9929 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
9930 if (mesh->numtriangles < mesh->maxtriangles)
9935 mesh->numtriangles++;
9937 element[1] = element[2];
9941 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
9942 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
9944 int planenum, planenum2;
9947 mplane_t *plane, *plane2;
9949 double temppoints[2][256*3];
9950 // figure out how large a bounding box we need to properly compute this brush
9952 for (w = 0;w < numplanes;w++)
9953 maxdist = max(maxdist, fabs(planes[w].dist));
9954 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
9955 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
9956 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
9960 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
9961 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
9963 if (planenum2 == planenum)
9965 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);
9968 if (tempnumpoints < 3)
9970 // generate elements forming a triangle fan for this polygon
9971 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
9975 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)
9977 texturelayer_t *layer;
9978 layer = t->currentlayers + t->currentnumlayers++;
9980 layer->depthmask = depthmask;
9981 layer->blendfunc1 = blendfunc1;
9982 layer->blendfunc2 = blendfunc2;
9983 layer->texture = texture;
9984 layer->texmatrix = *matrix;
9985 layer->color[0] = r;
9986 layer->color[1] = g;
9987 layer->color[2] = b;
9988 layer->color[3] = a;
9991 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
9993 if(parms[0] == 0 && parms[1] == 0)
9995 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
9996 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10001 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10004 index = parms[2] + r_refdef.scene.time * parms[3];
10005 index -= floor(index);
10006 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10009 case Q3WAVEFUNC_NONE:
10010 case Q3WAVEFUNC_NOISE:
10011 case Q3WAVEFUNC_COUNT:
10014 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10015 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10016 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10017 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10018 case Q3WAVEFUNC_TRIANGLE:
10020 f = index - floor(index);
10023 else if (index < 2)
10025 else if (index < 3)
10031 f = parms[0] + parms[1] * f;
10032 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10033 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10037 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10042 matrix4x4_t matrix, temp;
10043 switch(tcmod->tcmod)
10045 case Q3TCMOD_COUNT:
10047 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10048 matrix = r_waterscrollmatrix;
10050 matrix = identitymatrix;
10052 case Q3TCMOD_ENTITYTRANSLATE:
10053 // this is used in Q3 to allow the gamecode to control texcoord
10054 // scrolling on the entity, which is not supported in darkplaces yet.
10055 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10057 case Q3TCMOD_ROTATE:
10058 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10059 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10060 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10062 case Q3TCMOD_SCALE:
10063 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10065 case Q3TCMOD_SCROLL:
10066 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10068 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10069 w = (int) tcmod->parms[0];
10070 h = (int) tcmod->parms[1];
10071 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10073 idx = (int) floor(f * w * h);
10074 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10076 case Q3TCMOD_STRETCH:
10077 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10078 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10080 case Q3TCMOD_TRANSFORM:
10081 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
10082 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
10083 VectorSet(tcmat + 6, 0 , 0 , 1);
10084 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
10085 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10087 case Q3TCMOD_TURBULENT:
10088 // this is handled in the RSurf_PrepareVertices function
10089 matrix = identitymatrix;
10093 Matrix4x4_Concat(texmatrix, &matrix, &temp);
10096 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10098 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10099 char name[MAX_QPATH];
10100 skinframe_t *skinframe;
10101 unsigned char pixels[296*194];
10102 strlcpy(cache->name, skinname, sizeof(cache->name));
10103 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10104 if (developer_loading.integer)
10105 Con_Printf("loading %s\n", name);
10106 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10107 if (!skinframe || !skinframe->base)
10110 fs_offset_t filesize;
10112 f = FS_LoadFile(name, tempmempool, true, &filesize);
10115 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10116 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10120 cache->skinframe = skinframe;
10123 texture_t *R_GetCurrentTexture(texture_t *t)
10126 const entity_render_t *ent = rsurface.entity;
10127 dp_model_t *model = ent->model;
10128 q3shaderinfo_layer_tcmod_t *tcmod;
10130 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10131 return t->currentframe;
10132 t->update_lastrenderframe = r_textureframe;
10133 t->update_lastrenderentity = (void *)ent;
10135 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10136 t->camera_entity = ent->entitynumber;
10138 t->camera_entity = 0;
10140 // switch to an alternate material if this is a q1bsp animated material
10142 texture_t *texture = t;
10143 int s = rsurface.ent_skinnum;
10144 if ((unsigned int)s >= (unsigned int)model->numskins)
10146 if (model->skinscenes)
10148 if (model->skinscenes[s].framecount > 1)
10149 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10151 s = model->skinscenes[s].firstframe;
10154 t = t + s * model->num_surfaces;
10157 // use an alternate animation if the entity's frame is not 0,
10158 // and only if the texture has an alternate animation
10159 if (rsurface.ent_alttextures && t->anim_total[1])
10160 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10162 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10164 texture->currentframe = t;
10167 // update currentskinframe to be a qw skin or animation frame
10168 if (rsurface.ent_qwskin >= 0)
10170 i = rsurface.ent_qwskin;
10171 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10173 r_qwskincache_size = cl.maxclients;
10175 Mem_Free(r_qwskincache);
10176 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10178 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10179 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10180 t->currentskinframe = r_qwskincache[i].skinframe;
10181 if (t->currentskinframe == NULL)
10182 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10184 else if (t->numskinframes >= 2)
10185 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10186 if (t->backgroundnumskinframes >= 2)
10187 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10189 t->currentmaterialflags = t->basematerialflags;
10190 t->currentalpha = rsurface.colormod[3];
10191 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10192 t->currentalpha *= r_wateralpha.value;
10193 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10194 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10195 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10196 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10197 if (!(rsurface.ent_flags & RENDER_LIGHT))
10198 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10199 else if (FAKELIGHT_ENABLED)
10201 // no modellight if using fakelight for the map
10203 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10205 // pick a model lighting mode
10206 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10207 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10209 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10211 if (rsurface.ent_flags & RENDER_ADDITIVE)
10212 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10213 else if (t->currentalpha < 1)
10214 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10215 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10216 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10217 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10218 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10219 if (t->backgroundnumskinframes)
10220 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10221 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10223 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10224 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10227 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10228 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10229 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10231 // there is no tcmod
10232 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10234 t->currenttexmatrix = r_waterscrollmatrix;
10235 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10237 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10239 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10240 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10243 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10244 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10245 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10246 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10248 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10249 if (t->currentskinframe->qpixels)
10250 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10251 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10252 if (!t->basetexture)
10253 t->basetexture = r_texture_notexture;
10254 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10255 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10256 t->nmaptexture = t->currentskinframe->nmap;
10257 if (!t->nmaptexture)
10258 t->nmaptexture = r_texture_blanknormalmap;
10259 t->glosstexture = r_texture_black;
10260 t->glowtexture = t->currentskinframe->glow;
10261 t->fogtexture = t->currentskinframe->fog;
10262 t->reflectmasktexture = t->currentskinframe->reflect;
10263 if (t->backgroundnumskinframes)
10265 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10266 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10267 t->backgroundglosstexture = r_texture_black;
10268 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10269 if (!t->backgroundnmaptexture)
10270 t->backgroundnmaptexture = r_texture_blanknormalmap;
10274 t->backgroundbasetexture = r_texture_white;
10275 t->backgroundnmaptexture = r_texture_blanknormalmap;
10276 t->backgroundglosstexture = r_texture_black;
10277 t->backgroundglowtexture = NULL;
10279 t->specularpower = r_shadow_glossexponent.value;
10280 // TODO: store reference values for these in the texture?
10281 t->specularscale = 0;
10282 if (r_shadow_gloss.integer > 0)
10284 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10286 if (r_shadow_glossintensity.value > 0)
10288 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10289 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10290 t->specularscale = r_shadow_glossintensity.value;
10293 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10295 t->glosstexture = r_texture_white;
10296 t->backgroundglosstexture = r_texture_white;
10297 t->specularscale = r_shadow_gloss2intensity.value;
10298 t->specularpower = r_shadow_gloss2exponent.value;
10301 t->specularscale *= t->specularscalemod;
10302 t->specularpower *= t->specularpowermod;
10304 // lightmaps mode looks bad with dlights using actual texturing, so turn
10305 // off the colormap and glossmap, but leave the normalmap on as it still
10306 // accurately represents the shading involved
10307 if (gl_lightmaps.integer)
10309 t->basetexture = r_texture_grey128;
10310 t->pantstexture = r_texture_black;
10311 t->shirttexture = r_texture_black;
10312 t->nmaptexture = r_texture_blanknormalmap;
10313 t->glosstexture = r_texture_black;
10314 t->glowtexture = NULL;
10315 t->fogtexture = NULL;
10316 t->reflectmasktexture = NULL;
10317 t->backgroundbasetexture = NULL;
10318 t->backgroundnmaptexture = r_texture_blanknormalmap;
10319 t->backgroundglosstexture = r_texture_black;
10320 t->backgroundglowtexture = NULL;
10321 t->specularscale = 0;
10322 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10325 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10326 VectorClear(t->dlightcolor);
10327 t->currentnumlayers = 0;
10328 if (t->currentmaterialflags & MATERIALFLAG_WALL)
10330 int blendfunc1, blendfunc2;
10331 qboolean depthmask;
10332 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10334 blendfunc1 = GL_SRC_ALPHA;
10335 blendfunc2 = GL_ONE;
10337 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10339 blendfunc1 = GL_SRC_ALPHA;
10340 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10342 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10344 blendfunc1 = t->customblendfunc[0];
10345 blendfunc2 = t->customblendfunc[1];
10349 blendfunc1 = GL_ONE;
10350 blendfunc2 = GL_ZERO;
10352 // don't colormod evilblend textures
10353 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10354 VectorSet(t->lightmapcolor, 1, 1, 1);
10355 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10356 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10358 // fullbright is not affected by r_refdef.lightmapintensity
10359 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]);
10360 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10361 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]);
10362 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10363 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]);
10367 vec3_t ambientcolor;
10369 // set the color tint used for lights affecting this surface
10370 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10372 // q3bsp has no lightmap updates, so the lightstylevalue that
10373 // would normally be baked into the lightmap must be
10374 // applied to the color
10375 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10376 if (model->type == mod_brushq3)
10377 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10378 colorscale *= r_refdef.lightmapintensity;
10379 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10380 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10381 // basic lit geometry
10382 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]);
10383 // add pants/shirt if needed
10384 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10385 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]);
10386 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10387 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]);
10388 // now add ambient passes if needed
10389 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10391 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]);
10392 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10393 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]);
10394 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10395 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]);
10398 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10399 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]);
10400 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10402 // if this is opaque use alpha blend which will darken the earlier
10405 // if this is an alpha blended material, all the earlier passes
10406 // were darkened by fog already, so we only need to add the fog
10407 // color ontop through the fog mask texture
10409 // if this is an additive blended material, all the earlier passes
10410 // were darkened by fog already, and we should not add fog color
10411 // (because the background was not darkened, there is no fog color
10412 // that was lost behind it).
10413 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]);
10417 return t->currentframe;
10420 rsurfacestate_t rsurface;
10422 void RSurf_ActiveWorldEntity(void)
10424 dp_model_t *model = r_refdef.scene.worldmodel;
10425 //if (rsurface.entity == r_refdef.scene.worldentity)
10427 rsurface.entity = r_refdef.scene.worldentity;
10428 rsurface.skeleton = NULL;
10429 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10430 rsurface.ent_skinnum = 0;
10431 rsurface.ent_qwskin = -1;
10432 rsurface.ent_shadertime = 0;
10433 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10434 rsurface.matrix = identitymatrix;
10435 rsurface.inversematrix = identitymatrix;
10436 rsurface.matrixscale = 1;
10437 rsurface.inversematrixscale = 1;
10438 R_EntityMatrix(&identitymatrix);
10439 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10440 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10441 rsurface.fograngerecip = r_refdef.fograngerecip;
10442 rsurface.fogheightfade = r_refdef.fogheightfade;
10443 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10444 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10445 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10446 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10447 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10448 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10449 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10450 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10451 rsurface.colormod[3] = 1;
10452 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);
10453 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10454 rsurface.frameblend[0].lerp = 1;
10455 rsurface.ent_alttextures = false;
10456 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10457 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10458 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
10459 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10460 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10461 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10462 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10463 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10464 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10465 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10466 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10467 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
10468 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10469 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10470 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
10471 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10472 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10473 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
10474 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10475 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10476 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
10477 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10478 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10479 rsurface.modelelement3i = model->surfmesh.data_element3i;
10480 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10481 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10482 rsurface.modelelement3s = model->surfmesh.data_element3s;
10483 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10484 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10485 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10486 rsurface.modelnumvertices = model->surfmesh.num_vertices;
10487 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10488 rsurface.modelsurfaces = model->data_surfaces;
10489 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10490 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10491 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
10492 rsurface.modelgeneratedvertex = false;
10493 rsurface.batchgeneratedvertex = false;
10494 rsurface.batchfirstvertex = 0;
10495 rsurface.batchnumvertices = 0;
10496 rsurface.batchfirsttriangle = 0;
10497 rsurface.batchnumtriangles = 0;
10498 rsurface.batchvertex3f = NULL;
10499 rsurface.batchvertex3f_vertexbuffer = NULL;
10500 rsurface.batchvertex3f_bufferoffset = 0;
10501 rsurface.batchsvector3f = NULL;
10502 rsurface.batchsvector3f_vertexbuffer = NULL;
10503 rsurface.batchsvector3f_bufferoffset = 0;
10504 rsurface.batchtvector3f = NULL;
10505 rsurface.batchtvector3f_vertexbuffer = NULL;
10506 rsurface.batchtvector3f_bufferoffset = 0;
10507 rsurface.batchnormal3f = NULL;
10508 rsurface.batchnormal3f_vertexbuffer = NULL;
10509 rsurface.batchnormal3f_bufferoffset = 0;
10510 rsurface.batchlightmapcolor4f = NULL;
10511 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10512 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10513 rsurface.batchtexcoordtexture2f = NULL;
10514 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10515 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10516 rsurface.batchtexcoordlightmap2f = NULL;
10517 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10518 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10519 rsurface.batchvertexmesh = NULL;
10520 rsurface.batchvertexmeshbuffer = NULL;
10521 rsurface.batchvertex3fbuffer = NULL;
10522 rsurface.batchelement3i = NULL;
10523 rsurface.batchelement3i_indexbuffer = NULL;
10524 rsurface.batchelement3i_bufferoffset = 0;
10525 rsurface.batchelement3s = NULL;
10526 rsurface.batchelement3s_indexbuffer = NULL;
10527 rsurface.batchelement3s_bufferoffset = 0;
10528 rsurface.passcolor4f = NULL;
10529 rsurface.passcolor4f_vertexbuffer = NULL;
10530 rsurface.passcolor4f_bufferoffset = 0;
10533 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10535 dp_model_t *model = ent->model;
10536 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10538 rsurface.entity = (entity_render_t *)ent;
10539 rsurface.skeleton = ent->skeleton;
10540 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10541 rsurface.ent_skinnum = ent->skinnum;
10542 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;
10543 rsurface.ent_shadertime = ent->shadertime;
10544 rsurface.ent_flags = ent->flags;
10545 rsurface.matrix = ent->matrix;
10546 rsurface.inversematrix = ent->inversematrix;
10547 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10548 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10549 R_EntityMatrix(&rsurface.matrix);
10550 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10551 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10552 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10553 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10554 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10555 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10556 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10557 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10558 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10559 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10560 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10561 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10562 rsurface.colormod[3] = ent->alpha;
10563 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10564 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10565 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10566 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10567 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10568 if (ent->model->brush.submodel && !prepass)
10570 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10571 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10573 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10575 if (ent->animcache_vertex3f)
10577 rsurface.modelvertex3f = ent->animcache_vertex3f;
10578 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10579 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10580 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10581 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
10582 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
10583 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
10585 else if (wanttangents)
10587 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10588 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10589 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10590 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10591 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
10592 rsurface.modelvertexmesh = NULL;
10593 rsurface.modelvertexmeshbuffer = NULL;
10594 rsurface.modelvertex3fbuffer = NULL;
10596 else if (wantnormals)
10598 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10599 rsurface.modelsvector3f = NULL;
10600 rsurface.modeltvector3f = NULL;
10601 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10602 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
10603 rsurface.modelvertexmesh = NULL;
10604 rsurface.modelvertexmeshbuffer = NULL;
10605 rsurface.modelvertex3fbuffer = NULL;
10609 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10610 rsurface.modelsvector3f = NULL;
10611 rsurface.modeltvector3f = NULL;
10612 rsurface.modelnormal3f = NULL;
10613 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
10614 rsurface.modelvertexmesh = NULL;
10615 rsurface.modelvertexmeshbuffer = NULL;
10616 rsurface.modelvertex3fbuffer = NULL;
10618 rsurface.modelvertex3f_vertexbuffer = 0;
10619 rsurface.modelvertex3f_bufferoffset = 0;
10620 rsurface.modelsvector3f_vertexbuffer = 0;
10621 rsurface.modelsvector3f_bufferoffset = 0;
10622 rsurface.modeltvector3f_vertexbuffer = 0;
10623 rsurface.modeltvector3f_bufferoffset = 0;
10624 rsurface.modelnormal3f_vertexbuffer = 0;
10625 rsurface.modelnormal3f_bufferoffset = 0;
10626 rsurface.modelgeneratedvertex = true;
10630 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
10631 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10632 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10633 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10634 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10635 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10636 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10637 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10638 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10639 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
10640 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10641 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10642 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10643 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10644 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
10645 rsurface.modelgeneratedvertex = false;
10647 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
10648 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10649 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10650 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
10651 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10652 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10653 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
10654 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10655 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10656 rsurface.modelelement3i = model->surfmesh.data_element3i;
10657 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10658 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10659 rsurface.modelelement3s = model->surfmesh.data_element3s;
10660 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10661 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10662 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10663 rsurface.modelnumvertices = model->surfmesh.num_vertices;
10664 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10665 rsurface.modelsurfaces = model->data_surfaces;
10666 rsurface.batchgeneratedvertex = false;
10667 rsurface.batchfirstvertex = 0;
10668 rsurface.batchnumvertices = 0;
10669 rsurface.batchfirsttriangle = 0;
10670 rsurface.batchnumtriangles = 0;
10671 rsurface.batchvertex3f = NULL;
10672 rsurface.batchvertex3f_vertexbuffer = NULL;
10673 rsurface.batchvertex3f_bufferoffset = 0;
10674 rsurface.batchsvector3f = NULL;
10675 rsurface.batchsvector3f_vertexbuffer = NULL;
10676 rsurface.batchsvector3f_bufferoffset = 0;
10677 rsurface.batchtvector3f = NULL;
10678 rsurface.batchtvector3f_vertexbuffer = NULL;
10679 rsurface.batchtvector3f_bufferoffset = 0;
10680 rsurface.batchnormal3f = NULL;
10681 rsurface.batchnormal3f_vertexbuffer = NULL;
10682 rsurface.batchnormal3f_bufferoffset = 0;
10683 rsurface.batchlightmapcolor4f = NULL;
10684 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10685 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10686 rsurface.batchtexcoordtexture2f = NULL;
10687 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10688 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10689 rsurface.batchtexcoordlightmap2f = NULL;
10690 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10691 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10692 rsurface.batchvertexmesh = NULL;
10693 rsurface.batchvertexmeshbuffer = NULL;
10694 rsurface.batchvertex3fbuffer = NULL;
10695 rsurface.batchelement3i = NULL;
10696 rsurface.batchelement3i_indexbuffer = NULL;
10697 rsurface.batchelement3i_bufferoffset = 0;
10698 rsurface.batchelement3s = NULL;
10699 rsurface.batchelement3s_indexbuffer = NULL;
10700 rsurface.batchelement3s_bufferoffset = 0;
10701 rsurface.passcolor4f = NULL;
10702 rsurface.passcolor4f_vertexbuffer = NULL;
10703 rsurface.passcolor4f_bufferoffset = 0;
10706 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)
10708 rsurface.entity = r_refdef.scene.worldentity;
10709 rsurface.skeleton = NULL;
10710 rsurface.ent_skinnum = 0;
10711 rsurface.ent_qwskin = -1;
10712 rsurface.ent_shadertime = shadertime;
10713 rsurface.ent_flags = entflags;
10714 rsurface.modelnumvertices = numvertices;
10715 rsurface.modelnumtriangles = numtriangles;
10716 rsurface.matrix = *matrix;
10717 rsurface.inversematrix = *inversematrix;
10718 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10719 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10720 R_EntityMatrix(&rsurface.matrix);
10721 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10722 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10723 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10724 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10725 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10726 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10727 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10728 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10729 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10730 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10731 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10732 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
10733 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);
10734 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10735 rsurface.frameblend[0].lerp = 1;
10736 rsurface.ent_alttextures = false;
10737 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10738 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10741 rsurface.modelvertex3f = (float *)vertex3f;
10742 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10743 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10744 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10746 else if (wantnormals)
10748 rsurface.modelvertex3f = (float *)vertex3f;
10749 rsurface.modelsvector3f = NULL;
10750 rsurface.modeltvector3f = NULL;
10751 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10755 rsurface.modelvertex3f = (float *)vertex3f;
10756 rsurface.modelsvector3f = NULL;
10757 rsurface.modeltvector3f = NULL;
10758 rsurface.modelnormal3f = NULL;
10760 rsurface.modelvertexmesh = NULL;
10761 rsurface.modelvertexmeshbuffer = NULL;
10762 rsurface.modelvertex3fbuffer = NULL;
10763 rsurface.modelvertex3f_vertexbuffer = 0;
10764 rsurface.modelvertex3f_bufferoffset = 0;
10765 rsurface.modelsvector3f_vertexbuffer = 0;
10766 rsurface.modelsvector3f_bufferoffset = 0;
10767 rsurface.modeltvector3f_vertexbuffer = 0;
10768 rsurface.modeltvector3f_bufferoffset = 0;
10769 rsurface.modelnormal3f_vertexbuffer = 0;
10770 rsurface.modelnormal3f_bufferoffset = 0;
10771 rsurface.modelgeneratedvertex = true;
10772 rsurface.modellightmapcolor4f = (float *)color4f;
10773 rsurface.modellightmapcolor4f_vertexbuffer = 0;
10774 rsurface.modellightmapcolor4f_bufferoffset = 0;
10775 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
10776 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
10777 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
10778 rsurface.modeltexcoordlightmap2f = NULL;
10779 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
10780 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
10781 rsurface.modelelement3i = (int *)element3i;
10782 rsurface.modelelement3i_indexbuffer = NULL;
10783 rsurface.modelelement3i_bufferoffset = 0;
10784 rsurface.modelelement3s = (unsigned short *)element3s;
10785 rsurface.modelelement3s_indexbuffer = NULL;
10786 rsurface.modelelement3s_bufferoffset = 0;
10787 rsurface.modellightmapoffsets = NULL;
10788 rsurface.modelsurfaces = NULL;
10789 rsurface.batchgeneratedvertex = false;
10790 rsurface.batchfirstvertex = 0;
10791 rsurface.batchnumvertices = 0;
10792 rsurface.batchfirsttriangle = 0;
10793 rsurface.batchnumtriangles = 0;
10794 rsurface.batchvertex3f = NULL;
10795 rsurface.batchvertex3f_vertexbuffer = NULL;
10796 rsurface.batchvertex3f_bufferoffset = 0;
10797 rsurface.batchsvector3f = NULL;
10798 rsurface.batchsvector3f_vertexbuffer = NULL;
10799 rsurface.batchsvector3f_bufferoffset = 0;
10800 rsurface.batchtvector3f = NULL;
10801 rsurface.batchtvector3f_vertexbuffer = NULL;
10802 rsurface.batchtvector3f_bufferoffset = 0;
10803 rsurface.batchnormal3f = NULL;
10804 rsurface.batchnormal3f_vertexbuffer = NULL;
10805 rsurface.batchnormal3f_bufferoffset = 0;
10806 rsurface.batchlightmapcolor4f = NULL;
10807 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10808 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10809 rsurface.batchtexcoordtexture2f = NULL;
10810 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10811 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10812 rsurface.batchtexcoordlightmap2f = NULL;
10813 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10814 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10815 rsurface.batchvertexmesh = NULL;
10816 rsurface.batchvertexmeshbuffer = NULL;
10817 rsurface.batchvertex3fbuffer = NULL;
10818 rsurface.batchelement3i = NULL;
10819 rsurface.batchelement3i_indexbuffer = NULL;
10820 rsurface.batchelement3i_bufferoffset = 0;
10821 rsurface.batchelement3s = NULL;
10822 rsurface.batchelement3s_indexbuffer = NULL;
10823 rsurface.batchelement3s_bufferoffset = 0;
10824 rsurface.passcolor4f = NULL;
10825 rsurface.passcolor4f_vertexbuffer = NULL;
10826 rsurface.passcolor4f_bufferoffset = 0;
10828 if (rsurface.modelnumvertices && rsurface.modelelement3i)
10830 if ((wantnormals || wanttangents) && !normal3f)
10832 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10833 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
10835 if (wanttangents && !svector3f)
10837 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10838 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10839 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
10844 float RSurf_FogPoint(const float *v)
10846 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10847 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
10848 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
10849 float FogHeightFade = r_refdef.fogheightfade;
10851 unsigned int fogmasktableindex;
10852 if (r_refdef.fogplaneviewabove)
10853 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10855 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10856 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
10857 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10860 float RSurf_FogVertex(const float *v)
10862 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10863 float FogPlaneViewDist = rsurface.fogplaneviewdist;
10864 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
10865 float FogHeightFade = rsurface.fogheightfade;
10867 unsigned int fogmasktableindex;
10868 if (r_refdef.fogplaneviewabove)
10869 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10871 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10872 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
10873 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10876 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
10879 for (i = 0;i < numelements;i++)
10880 outelement3i[i] = inelement3i[i] + adjust;
10883 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
10884 extern cvar_t gl_vbo;
10885 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
10893 int surfacefirsttriangle;
10894 int surfacenumtriangles;
10895 int surfacefirstvertex;
10896 int surfaceendvertex;
10897 int surfacenumvertices;
10898 int batchnumvertices;
10899 int batchnumtriangles;
10903 qboolean dynamicvertex;
10907 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
10908 float waveparms[4];
10909 q3shaderinfo_deform_t *deform;
10910 const msurface_t *surface, *firstsurface;
10911 r_vertexmesh_t *vertexmesh;
10912 if (!texturenumsurfaces)
10914 // find vertex range of this surface batch
10916 firstsurface = texturesurfacelist[0];
10917 firsttriangle = firstsurface->num_firsttriangle;
10918 batchnumvertices = 0;
10919 batchnumtriangles = 0;
10920 firstvertex = endvertex = firstsurface->num_firstvertex;
10921 for (i = 0;i < texturenumsurfaces;i++)
10923 surface = texturesurfacelist[i];
10924 if (surface != firstsurface + i)
10926 surfacefirstvertex = surface->num_firstvertex;
10927 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
10928 surfacenumvertices = surface->num_vertices;
10929 surfacenumtriangles = surface->num_triangles;
10930 if (firstvertex > surfacefirstvertex)
10931 firstvertex = surfacefirstvertex;
10932 if (endvertex < surfaceendvertex)
10933 endvertex = surfaceendvertex;
10934 batchnumvertices += surfacenumvertices;
10935 batchnumtriangles += surfacenumtriangles;
10938 // we now know the vertex range used, and if there are any gaps in it
10939 rsurface.batchfirstvertex = firstvertex;
10940 rsurface.batchnumvertices = endvertex - firstvertex;
10941 rsurface.batchfirsttriangle = firsttriangle;
10942 rsurface.batchnumtriangles = batchnumtriangles;
10944 // this variable holds flags for which properties have been updated that
10945 // may require regenerating vertexmesh array...
10948 // check if any dynamic vertex processing must occur
10949 dynamicvertex = false;
10951 // if there is a chance of animated vertex colors, it's a dynamic batch
10952 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
10954 dynamicvertex = true;
10955 batchneed |= BATCHNEED_NOGAPS;
10956 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
10959 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
10961 switch (deform->deform)
10964 case Q3DEFORM_PROJECTIONSHADOW:
10965 case Q3DEFORM_TEXT0:
10966 case Q3DEFORM_TEXT1:
10967 case Q3DEFORM_TEXT2:
10968 case Q3DEFORM_TEXT3:
10969 case Q3DEFORM_TEXT4:
10970 case Q3DEFORM_TEXT5:
10971 case Q3DEFORM_TEXT6:
10972 case Q3DEFORM_TEXT7:
10973 case Q3DEFORM_NONE:
10975 case Q3DEFORM_AUTOSPRITE:
10976 dynamicvertex = true;
10977 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10978 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10980 case Q3DEFORM_AUTOSPRITE2:
10981 dynamicvertex = true;
10982 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10983 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10985 case Q3DEFORM_NORMAL:
10986 dynamicvertex = true;
10987 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10988 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10990 case Q3DEFORM_WAVE:
10991 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10992 break; // if wavefunc is a nop, ignore this transform
10993 dynamicvertex = true;
10994 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10995 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10997 case Q3DEFORM_BULGE:
10998 dynamicvertex = true;
10999 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11000 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11002 case Q3DEFORM_MOVE:
11003 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11004 break; // if wavefunc is a nop, ignore this transform
11005 dynamicvertex = true;
11006 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11007 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
11011 switch(rsurface.texture->tcgen.tcgen)
11014 case Q3TCGEN_TEXTURE:
11016 case Q3TCGEN_LIGHTMAP:
11017 dynamicvertex = true;
11018 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11019 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11021 case Q3TCGEN_VECTOR:
11022 dynamicvertex = true;
11023 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11024 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11026 case Q3TCGEN_ENVIRONMENT:
11027 dynamicvertex = true;
11028 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11029 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11032 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11034 dynamicvertex = true;
11035 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11036 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11039 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11041 dynamicvertex = true;
11042 batchneed |= BATCHNEED_NOGAPS;
11043 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11046 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11048 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11049 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
11050 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
11051 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
11052 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11053 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11054 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11057 // when the model data has no vertex buffer (dynamic mesh), we need to
11059 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
11060 batchneed |= BATCHNEED_NOGAPS;
11062 // if needsupdate, we have to do a dynamic vertex batch for sure
11063 if (needsupdate & batchneed)
11064 dynamicvertex = true;
11066 // see if we need to build vertexmesh from arrays
11067 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11068 dynamicvertex = true;
11070 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11071 // also some drivers strongly dislike firstvertex
11072 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11073 dynamicvertex = true;
11075 rsurface.batchvertex3f = rsurface.modelvertex3f;
11076 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11077 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11078 rsurface.batchsvector3f = rsurface.modelsvector3f;
11079 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11080 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11081 rsurface.batchtvector3f = rsurface.modeltvector3f;
11082 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11083 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11084 rsurface.batchnormal3f = rsurface.modelnormal3f;
11085 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11086 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11087 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11088 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
11089 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11090 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11091 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
11092 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
11093 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11094 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11095 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11096 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
11097 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11098 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11099 rsurface.batchelement3i = rsurface.modelelement3i;
11100 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11101 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11102 rsurface.batchelement3s = rsurface.modelelement3s;
11103 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11104 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11106 // if any dynamic vertex processing has to occur in software, we copy the
11107 // entire surface list together before processing to rebase the vertices
11108 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11110 // if any gaps exist and we do not have a static vertex buffer, we have to
11111 // copy the surface list together to avoid wasting upload bandwidth on the
11112 // vertices in the gaps.
11114 // if gaps exist and we have a static vertex buffer, we still have to
11115 // combine the index buffer ranges into one dynamic index buffer.
11117 // in all cases we end up with data that can be drawn in one call.
11119 if (!dynamicvertex)
11121 // static vertex data, just set pointers...
11122 rsurface.batchgeneratedvertex = false;
11123 // if there are gaps, we want to build a combined index buffer,
11124 // otherwise use the original static buffer with an appropriate offset
11127 // build a new triangle elements array for this batch
11128 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11129 rsurface.batchfirsttriangle = 0;
11131 for (i = 0;i < texturenumsurfaces;i++)
11133 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11134 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11135 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11136 numtriangles += surfacenumtriangles;
11138 rsurface.batchelement3i_indexbuffer = NULL;
11139 rsurface.batchelement3i_bufferoffset = 0;
11140 rsurface.batchelement3s = NULL;
11141 rsurface.batchelement3s_indexbuffer = NULL;
11142 rsurface.batchelement3s_bufferoffset = 0;
11143 if (endvertex <= 65536)
11145 // make a 16bit (unsigned short) index array if possible
11146 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11147 for (i = 0;i < numtriangles*3;i++)
11148 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11154 // something needs software processing, do it for real...
11155 // we only directly handle separate array data in this case and then
11156 // generate interleaved data if needed...
11157 rsurface.batchgeneratedvertex = true;
11159 // now copy the vertex data into a combined array and make an index array
11160 // (this is what Quake3 does all the time)
11161 //if (gaps || rsurface.batchfirstvertex)
11163 rsurface.batchvertex3fbuffer = NULL;
11164 rsurface.batchvertexmesh = NULL;
11165 rsurface.batchvertexmeshbuffer = NULL;
11166 rsurface.batchvertex3f = NULL;
11167 rsurface.batchvertex3f_vertexbuffer = NULL;
11168 rsurface.batchvertex3f_bufferoffset = 0;
11169 rsurface.batchsvector3f = NULL;
11170 rsurface.batchsvector3f_vertexbuffer = NULL;
11171 rsurface.batchsvector3f_bufferoffset = 0;
11172 rsurface.batchtvector3f = NULL;
11173 rsurface.batchtvector3f_vertexbuffer = NULL;
11174 rsurface.batchtvector3f_bufferoffset = 0;
11175 rsurface.batchnormal3f = NULL;
11176 rsurface.batchnormal3f_vertexbuffer = NULL;
11177 rsurface.batchnormal3f_bufferoffset = 0;
11178 rsurface.batchlightmapcolor4f = NULL;
11179 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11180 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11181 rsurface.batchtexcoordtexture2f = NULL;
11182 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11183 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11184 rsurface.batchtexcoordlightmap2f = NULL;
11185 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11186 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11187 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11188 rsurface.batchelement3i_indexbuffer = NULL;
11189 rsurface.batchelement3i_bufferoffset = 0;
11190 rsurface.batchelement3s = NULL;
11191 rsurface.batchelement3s_indexbuffer = NULL;
11192 rsurface.batchelement3s_bufferoffset = 0;
11193 // we'll only be setting up certain arrays as needed
11194 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11195 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
11196 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11197 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11198 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11199 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11200 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11202 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11203 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11205 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11206 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11207 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11208 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11209 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11210 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11213 for (i = 0;i < texturenumsurfaces;i++)
11215 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11216 surfacenumvertices = texturesurfacelist[i]->num_vertices;
11217 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11218 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11219 // copy only the data requested
11220 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11221 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11222 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11224 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11225 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11226 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11227 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11228 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11230 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11231 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11233 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11234 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11235 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11236 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11237 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11238 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11240 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11241 numvertices += surfacenumvertices;
11242 numtriangles += surfacenumtriangles;
11245 // generate a 16bit index array as well if possible
11246 // (in general, dynamic batches fit)
11247 if (numvertices <= 65536)
11249 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11250 for (i = 0;i < numtriangles*3;i++)
11251 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11254 // since we've copied everything, the batch now starts at 0
11255 rsurface.batchfirstvertex = 0;
11256 rsurface.batchnumvertices = batchnumvertices;
11257 rsurface.batchfirsttriangle = 0;
11258 rsurface.batchnumtriangles = batchnumtriangles;
11261 // q1bsp surfaces rendered in vertex color mode have to have colors
11262 // calculated based on lightstyles
11263 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11265 // generate color arrays for the surfaces in this list
11269 const int *offsets;
11270 const unsigned char *lm;
11271 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11272 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11273 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11275 for (i = 0;i < texturenumsurfaces;i++)
11277 surface = texturesurfacelist[i];
11278 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11279 surfacenumvertices = surface->num_vertices;
11280 if (surface->lightmapinfo->samples)
11282 for (j = 0;j < surfacenumvertices;j++)
11284 lm = surface->lightmapinfo->samples + offsets[j];
11285 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11286 VectorScale(lm, scale, c);
11287 if (surface->lightmapinfo->styles[1] != 255)
11289 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11291 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11292 VectorMA(c, scale, lm, c);
11293 if (surface->lightmapinfo->styles[2] != 255)
11296 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11297 VectorMA(c, scale, lm, c);
11298 if (surface->lightmapinfo->styles[3] != 255)
11301 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11302 VectorMA(c, scale, lm, c);
11309 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);
11315 for (j = 0;j < surfacenumvertices;j++)
11317 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11324 // if vertices are deformed (sprite flares and things in maps, possibly
11325 // water waves, bulges and other deformations), modify the copied vertices
11327 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11329 switch (deform->deform)
11332 case Q3DEFORM_PROJECTIONSHADOW:
11333 case Q3DEFORM_TEXT0:
11334 case Q3DEFORM_TEXT1:
11335 case Q3DEFORM_TEXT2:
11336 case Q3DEFORM_TEXT3:
11337 case Q3DEFORM_TEXT4:
11338 case Q3DEFORM_TEXT5:
11339 case Q3DEFORM_TEXT6:
11340 case Q3DEFORM_TEXT7:
11341 case Q3DEFORM_NONE:
11343 case Q3DEFORM_AUTOSPRITE:
11344 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11345 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11346 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11347 VectorNormalize(newforward);
11348 VectorNormalize(newright);
11349 VectorNormalize(newup);
11350 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11351 // rsurface.batchvertex3f_vertexbuffer = NULL;
11352 // rsurface.batchvertex3f_bufferoffset = 0;
11353 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
11354 // rsurface.batchsvector3f_vertexbuffer = NULL;
11355 // rsurface.batchsvector3f_bufferoffset = 0;
11356 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
11357 // rsurface.batchtvector3f_vertexbuffer = NULL;
11358 // rsurface.batchtvector3f_bufferoffset = 0;
11359 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11360 // rsurface.batchnormal3f_vertexbuffer = NULL;
11361 // rsurface.batchnormal3f_bufferoffset = 0;
11362 // a single autosprite surface can contain multiple sprites...
11363 for (j = 0;j < batchnumvertices - 3;j += 4)
11365 VectorClear(center);
11366 for (i = 0;i < 4;i++)
11367 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11368 VectorScale(center, 0.25f, center);
11369 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11370 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11371 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11372 for (i = 0;i < 4;i++)
11374 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11375 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
11378 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11379 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11380 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);
11382 case Q3DEFORM_AUTOSPRITE2:
11383 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11384 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11385 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11386 VectorNormalize(newforward);
11387 VectorNormalize(newright);
11388 VectorNormalize(newup);
11389 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11390 // rsurface.batchvertex3f_vertexbuffer = NULL;
11391 // rsurface.batchvertex3f_bufferoffset = 0;
11393 const float *v1, *v2;
11403 memset(shortest, 0, sizeof(shortest));
11404 // a single autosprite surface can contain multiple sprites...
11405 for (j = 0;j < batchnumvertices - 3;j += 4)
11407 VectorClear(center);
11408 for (i = 0;i < 4;i++)
11409 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11410 VectorScale(center, 0.25f, center);
11411 // find the two shortest edges, then use them to define the
11412 // axis vectors for rotating around the central axis
11413 for (i = 0;i < 6;i++)
11415 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11416 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11417 l = VectorDistance2(v1, v2);
11418 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11419 if (v1[2] != v2[2])
11420 l += (1.0f / 1024.0f);
11421 if (shortest[0].length2 > l || i == 0)
11423 shortest[1] = shortest[0];
11424 shortest[0].length2 = l;
11425 shortest[0].v1 = v1;
11426 shortest[0].v2 = v2;
11428 else if (shortest[1].length2 > l || i == 1)
11430 shortest[1].length2 = l;
11431 shortest[1].v1 = v1;
11432 shortest[1].v2 = v2;
11435 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11436 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11437 // this calculates the right vector from the shortest edge
11438 // and the up vector from the edge midpoints
11439 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11440 VectorNormalize(right);
11441 VectorSubtract(end, start, up);
11442 VectorNormalize(up);
11443 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11444 VectorSubtract(rsurface.localvieworigin, center, forward);
11445 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11446 VectorNegate(forward, forward);
11447 VectorReflect(forward, 0, up, forward);
11448 VectorNormalize(forward);
11449 CrossProduct(up, forward, newright);
11450 VectorNormalize(newright);
11451 // rotate the quad around the up axis vector, this is made
11452 // especially easy by the fact we know the quad is flat,
11453 // so we only have to subtract the center position and
11454 // measure distance along the right vector, and then
11455 // multiply that by the newright vector and add back the
11457 // we also need to subtract the old position to undo the
11458 // displacement from the center, which we do with a
11459 // DotProduct, the subtraction/addition of center is also
11460 // optimized into DotProducts here
11461 l = DotProduct(right, center);
11462 for (i = 0;i < 4;i++)
11464 v1 = rsurface.batchvertex3f + 3*(j+i);
11465 f = DotProduct(right, v1) - l;
11466 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
11470 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11472 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11473 // rsurface.batchnormal3f_vertexbuffer = NULL;
11474 // rsurface.batchnormal3f_bufferoffset = 0;
11475 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11477 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11479 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11480 // rsurface.batchsvector3f_vertexbuffer = NULL;
11481 // rsurface.batchsvector3f_bufferoffset = 0;
11482 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11483 // rsurface.batchtvector3f_vertexbuffer = NULL;
11484 // rsurface.batchtvector3f_bufferoffset = 0;
11485 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);
11488 case Q3DEFORM_NORMAL:
11489 // deform the normals to make reflections wavey
11490 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11491 rsurface.batchnormal3f_vertexbuffer = NULL;
11492 rsurface.batchnormal3f_bufferoffset = 0;
11493 for (j = 0;j < batchnumvertices;j++)
11496 float *normal = rsurface.batchnormal3f + 3*j;
11497 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11498 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11499 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]);
11500 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]);
11501 VectorNormalize(normal);
11503 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11505 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11506 // rsurface.batchsvector3f_vertexbuffer = NULL;
11507 // rsurface.batchsvector3f_bufferoffset = 0;
11508 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11509 // rsurface.batchtvector3f_vertexbuffer = NULL;
11510 // rsurface.batchtvector3f_bufferoffset = 0;
11511 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);
11514 case Q3DEFORM_WAVE:
11515 // deform vertex array to make wavey water and flags and such
11516 waveparms[0] = deform->waveparms[0];
11517 waveparms[1] = deform->waveparms[1];
11518 waveparms[2] = deform->waveparms[2];
11519 waveparms[3] = deform->waveparms[3];
11520 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11521 break; // if wavefunc is a nop, don't make a dynamic vertex array
11522 // this is how a divisor of vertex influence on deformation
11523 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11524 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11525 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11526 // rsurface.batchvertex3f_vertexbuffer = NULL;
11527 // rsurface.batchvertex3f_bufferoffset = 0;
11528 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11529 // rsurface.batchnormal3f_vertexbuffer = NULL;
11530 // rsurface.batchnormal3f_bufferoffset = 0;
11531 for (j = 0;j < batchnumvertices;j++)
11533 // if the wavefunc depends on time, evaluate it per-vertex
11536 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11537 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11539 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
11541 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11542 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11543 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11545 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11546 // rsurface.batchsvector3f_vertexbuffer = NULL;
11547 // rsurface.batchsvector3f_bufferoffset = 0;
11548 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11549 // rsurface.batchtvector3f_vertexbuffer = NULL;
11550 // rsurface.batchtvector3f_bufferoffset = 0;
11551 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);
11554 case Q3DEFORM_BULGE:
11555 // deform vertex array to make the surface have moving bulges
11556 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11557 // rsurface.batchvertex3f_vertexbuffer = NULL;
11558 // rsurface.batchvertex3f_bufferoffset = 0;
11559 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11560 // rsurface.batchnormal3f_vertexbuffer = NULL;
11561 // rsurface.batchnormal3f_bufferoffset = 0;
11562 for (j = 0;j < batchnumvertices;j++)
11564 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
11565 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
11567 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11568 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11569 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11571 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11572 // rsurface.batchsvector3f_vertexbuffer = NULL;
11573 // rsurface.batchsvector3f_bufferoffset = 0;
11574 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11575 // rsurface.batchtvector3f_vertexbuffer = NULL;
11576 // rsurface.batchtvector3f_bufferoffset = 0;
11577 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);
11580 case Q3DEFORM_MOVE:
11581 // deform vertex array
11582 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11583 break; // if wavefunc is a nop, don't make a dynamic vertex array
11584 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
11585 VectorScale(deform->parms, scale, waveparms);
11586 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11587 // rsurface.batchvertex3f_vertexbuffer = NULL;
11588 // rsurface.batchvertex3f_bufferoffset = 0;
11589 for (j = 0;j < batchnumvertices;j++)
11590 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
11595 // generate texcoords based on the chosen texcoord source
11596 switch(rsurface.texture->tcgen.tcgen)
11599 case Q3TCGEN_TEXTURE:
11601 case Q3TCGEN_LIGHTMAP:
11602 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11603 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11604 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11605 if (rsurface.batchtexcoordlightmap2f)
11606 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
11608 case Q3TCGEN_VECTOR:
11609 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11610 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11611 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11612 for (j = 0;j < batchnumvertices;j++)
11614 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
11615 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
11618 case Q3TCGEN_ENVIRONMENT:
11619 // make environment reflections using a spheremap
11620 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11621 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11622 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11623 for (j = 0;j < batchnumvertices;j++)
11625 // identical to Q3A's method, but executed in worldspace so
11626 // carried models can be shiny too
11628 float viewer[3], d, reflected[3], worldreflected[3];
11630 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
11631 // VectorNormalize(viewer);
11633 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
11635 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
11636 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
11637 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
11638 // note: this is proportinal to viewer, so we can normalize later
11640 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
11641 VectorNormalize(worldreflected);
11643 // note: this sphere map only uses world x and z!
11644 // so positive and negative y will LOOK THE SAME.
11645 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
11646 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
11650 // the only tcmod that needs software vertex processing is turbulent, so
11651 // check for it here and apply the changes if needed
11652 // and we only support that as the first one
11653 // (handling a mixture of turbulent and other tcmods would be problematic
11654 // without punting it entirely to a software path)
11655 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11657 amplitude = rsurface.texture->tcmods[0].parms[1];
11658 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
11659 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11660 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11661 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11662 for (j = 0;j < batchnumvertices;j++)
11664 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);
11665 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
11669 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11671 // convert the modified arrays to vertex structs
11672 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
11673 // rsurface.batchvertexmeshbuffer = NULL;
11674 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
11675 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11676 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
11677 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
11678 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11679 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
11680 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
11682 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11684 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
11685 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
11688 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
11689 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11690 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
11691 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
11692 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11693 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
11694 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
11695 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11696 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
11700 void RSurf_DrawBatch(void)
11702 // sometimes a zero triangle surface (usually a degenerate patch) makes it
11703 // through the pipeline, killing it earlier in the pipeline would have
11704 // per-surface overhead rather than per-batch overhead, so it's best to
11705 // reject it here, before it hits glDraw.
11706 if (rsurface.batchnumtriangles == 0)
11709 // batch debugging code
11710 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
11716 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
11717 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
11720 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
11722 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
11724 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
11725 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);
11732 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);
11735 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
11737 // pick the closest matching water plane
11738 int planeindex, vertexindex, bestplaneindex = -1;
11742 r_waterstate_waterplane_t *p;
11743 qboolean prepared = false;
11745 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
11747 if(p->camera_entity != rsurface.texture->camera_entity)
11752 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11754 if(rsurface.batchnumvertices == 0)
11757 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
11759 Matrix4x4_Transform(&rsurface.matrix, v, vert);
11760 d += fabs(PlaneDiff(vert, &p->plane));
11762 if (bestd > d || bestplaneindex < 0)
11765 bestplaneindex = planeindex;
11768 return bestplaneindex;
11769 // NOTE: this MAY return a totally unrelated water plane; we can ignore
11770 // this situation though, as it might be better to render single larger
11771 // batches with useless stuff (backface culled for example) than to
11772 // render multiple smaller batches
11775 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
11778 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11779 rsurface.passcolor4f_vertexbuffer = 0;
11780 rsurface.passcolor4f_bufferoffset = 0;
11781 for (i = 0;i < rsurface.batchnumvertices;i++)
11782 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
11785 static void RSurf_DrawBatch_GL11_ApplyFog(void)
11792 if (rsurface.passcolor4f)
11794 // generate color arrays
11795 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11796 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11797 rsurface.passcolor4f_vertexbuffer = 0;
11798 rsurface.passcolor4f_bufferoffset = 0;
11799 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)
11801 f = RSurf_FogVertex(v);
11810 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11811 rsurface.passcolor4f_vertexbuffer = 0;
11812 rsurface.passcolor4f_bufferoffset = 0;
11813 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
11815 f = RSurf_FogVertex(v);
11824 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
11831 if (!rsurface.passcolor4f)
11833 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11834 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11835 rsurface.passcolor4f_vertexbuffer = 0;
11836 rsurface.passcolor4f_bufferoffset = 0;
11837 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)
11839 f = RSurf_FogVertex(v);
11840 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
11841 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
11842 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
11847 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
11852 if (!rsurface.passcolor4f)
11854 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11855 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11856 rsurface.passcolor4f_vertexbuffer = 0;
11857 rsurface.passcolor4f_bufferoffset = 0;
11858 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11867 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
11872 if (!rsurface.passcolor4f)
11874 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11875 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11876 rsurface.passcolor4f_vertexbuffer = 0;
11877 rsurface.passcolor4f_bufferoffset = 0;
11878 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11880 c2[0] = c[0] + r_refdef.scene.ambient;
11881 c2[1] = c[1] + r_refdef.scene.ambient;
11882 c2[2] = c[2] + r_refdef.scene.ambient;
11887 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11890 rsurface.passcolor4f = NULL;
11891 rsurface.passcolor4f_vertexbuffer = 0;
11892 rsurface.passcolor4f_bufferoffset = 0;
11893 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
11894 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11895 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11896 GL_Color(r, g, b, a);
11897 R_Mesh_TexBind(0, rsurface.lightmaptexture);
11901 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11903 // TODO: optimize applyfog && applycolor case
11904 // just apply fog if necessary, and tint the fog color array if necessary
11905 rsurface.passcolor4f = NULL;
11906 rsurface.passcolor4f_vertexbuffer = 0;
11907 rsurface.passcolor4f_bufferoffset = 0;
11908 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
11909 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11910 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11911 GL_Color(r, g, b, a);
11915 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11918 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11919 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11920 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11921 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
11922 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11923 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11924 GL_Color(r, g, b, a);
11928 static void RSurf_DrawBatch_GL11_ClampColor(void)
11933 if (!rsurface.passcolor4f)
11935 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
11937 c2[0] = bound(0.0f, c1[0], 1.0f);
11938 c2[1] = bound(0.0f, c1[1], 1.0f);
11939 c2[2] = bound(0.0f, c1[2], 1.0f);
11940 c2[3] = bound(0.0f, c1[3], 1.0f);
11944 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
11954 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11955 rsurface.passcolor4f_vertexbuffer = 0;
11956 rsurface.passcolor4f_bufferoffset = 0;
11957 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)
11959 f = -DotProduct(r_refdef.view.forward, n);
11961 f = f * 0.85 + 0.15; // work around so stuff won't get black
11962 f *= r_refdef.lightmapintensity;
11963 Vector4Set(c, f, f, f, 1);
11967 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11969 RSurf_DrawBatch_GL11_ApplyFakeLight();
11970 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
11971 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11972 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11973 GL_Color(r, g, b, a);
11977 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
11985 vec3_t ambientcolor;
11986 vec3_t diffusecolor;
11990 VectorCopy(rsurface.modellight_lightdir, lightdir);
11991 f = 0.5f * r_refdef.lightmapintensity;
11992 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
11993 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
11994 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
11995 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
11996 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
11997 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
11999 if (VectorLength2(diffusecolor) > 0)
12001 // q3-style directional shading
12002 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12003 rsurface.passcolor4f_vertexbuffer = 0;
12004 rsurface.passcolor4f_bufferoffset = 0;
12005 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)
12007 if ((f = DotProduct(n, lightdir)) > 0)
12008 VectorMA(ambientcolor, f, diffusecolor, c);
12010 VectorCopy(ambientcolor, c);
12017 *applycolor = false;
12021 *r = ambientcolor[0];
12022 *g = ambientcolor[1];
12023 *b = ambientcolor[2];
12024 rsurface.passcolor4f = NULL;
12025 rsurface.passcolor4f_vertexbuffer = 0;
12026 rsurface.passcolor4f_bufferoffset = 0;
12030 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12032 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12033 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12034 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12035 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12036 GL_Color(r, g, b, a);
12040 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12046 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12048 f = 1 - RSurf_FogVertex(v);
12056 void RSurf_SetupDepthAndCulling(void)
12058 // submodels are biased to avoid z-fighting with world surfaces that they
12059 // may be exactly overlapping (avoids z-fighting artifacts on certain
12060 // doors and things in Quake maps)
12061 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12062 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12063 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12064 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12067 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12069 // transparent sky would be ridiculous
12070 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12072 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12073 skyrenderlater = true;
12074 RSurf_SetupDepthAndCulling();
12075 GL_DepthMask(true);
12076 // LordHavoc: HalfLife maps have freaky skypolys so don't use
12077 // skymasking on them, and Quake3 never did sky masking (unlike
12078 // software Quake and software Quake2), so disable the sky masking
12079 // in Quake3 maps as it causes problems with q3map2 sky tricks,
12080 // and skymasking also looks very bad when noclipping outside the
12081 // level, so don't use it then either.
12082 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12084 R_Mesh_ResetTextureState();
12085 if (skyrendermasked)
12087 R_SetupShader_DepthOrShadow();
12088 // depth-only (masking)
12089 GL_ColorMask(0,0,0,0);
12090 // just to make sure that braindead drivers don't draw
12091 // anything despite that colormask...
12092 GL_BlendFunc(GL_ZERO, GL_ONE);
12093 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12094 if (rsurface.batchvertex3fbuffer)
12095 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12097 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12101 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12103 GL_BlendFunc(GL_ONE, GL_ZERO);
12104 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12105 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12106 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12109 if (skyrendermasked)
12110 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12112 R_Mesh_ResetTextureState();
12113 GL_Color(1, 1, 1, 1);
12116 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12117 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12118 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12120 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12124 // render screenspace normalmap to texture
12125 GL_DepthMask(true);
12126 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12131 // bind lightmap texture
12133 // water/refraction/reflection/camera surfaces have to be handled specially
12134 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
12136 int start, end, startplaneindex;
12137 for (start = 0;start < texturenumsurfaces;start = end)
12139 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12140 if(startplaneindex < 0)
12142 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
12143 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
12147 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12149 // now that we have a batch using the same planeindex, render it
12150 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
12152 // render water or distortion background
12153 GL_DepthMask(true);
12154 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));
12156 // blend surface on top
12157 GL_DepthMask(false);
12158 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12161 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
12163 // render surface with reflection texture as input
12164 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12165 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));
12172 // render surface batch normally
12173 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12174 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12178 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12180 // OpenGL 1.3 path - anything not completely ancient
12181 qboolean applycolor;
12184 const texturelayer_t *layer;
12185 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);
12186 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12188 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12191 int layertexrgbscale;
12192 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12194 if (layerindex == 0)
12195 GL_AlphaTest(true);
12198 GL_AlphaTest(false);
12199 GL_DepthFunc(GL_EQUAL);
12202 GL_DepthMask(layer->depthmask && writedepth);
12203 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12204 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12206 layertexrgbscale = 4;
12207 VectorScale(layer->color, 0.25f, layercolor);
12209 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12211 layertexrgbscale = 2;
12212 VectorScale(layer->color, 0.5f, layercolor);
12216 layertexrgbscale = 1;
12217 VectorScale(layer->color, 1.0f, layercolor);
12219 layercolor[3] = layer->color[3];
12220 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12221 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12222 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12223 switch (layer->type)
12225 case TEXTURELAYERTYPE_LITTEXTURE:
12226 // single-pass lightmapped texture with 2x rgbscale
12227 R_Mesh_TexBind(0, r_texture_white);
12228 R_Mesh_TexMatrix(0, NULL);
12229 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12230 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12231 R_Mesh_TexBind(1, layer->texture);
12232 R_Mesh_TexMatrix(1, &layer->texmatrix);
12233 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12234 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12235 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12236 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12237 else if (FAKELIGHT_ENABLED)
12238 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12239 else if (rsurface.uselightmaptexture)
12240 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12242 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12244 case TEXTURELAYERTYPE_TEXTURE:
12245 // singletexture unlit texture with transparency support
12246 R_Mesh_TexBind(0, layer->texture);
12247 R_Mesh_TexMatrix(0, &layer->texmatrix);
12248 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12249 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12250 R_Mesh_TexBind(1, 0);
12251 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12252 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12254 case TEXTURELAYERTYPE_FOG:
12255 // singletexture fogging
12256 if (layer->texture)
12258 R_Mesh_TexBind(0, layer->texture);
12259 R_Mesh_TexMatrix(0, &layer->texmatrix);
12260 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12261 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12265 R_Mesh_TexBind(0, 0);
12266 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12268 R_Mesh_TexBind(1, 0);
12269 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12270 // generate a color array for the fog pass
12271 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12272 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12276 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12279 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12281 GL_DepthFunc(GL_LEQUAL);
12282 GL_AlphaTest(false);
12286 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12288 // OpenGL 1.1 - crusty old voodoo path
12291 const texturelayer_t *layer;
12292 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);
12293 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12295 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12297 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12299 if (layerindex == 0)
12300 GL_AlphaTest(true);
12303 GL_AlphaTest(false);
12304 GL_DepthFunc(GL_EQUAL);
12307 GL_DepthMask(layer->depthmask && writedepth);
12308 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12309 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12310 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12311 switch (layer->type)
12313 case TEXTURELAYERTYPE_LITTEXTURE:
12314 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12316 // two-pass lit texture with 2x rgbscale
12317 // first the lightmap pass
12318 R_Mesh_TexBind(0, r_texture_white);
12319 R_Mesh_TexMatrix(0, NULL);
12320 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12321 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12322 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12323 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12324 else if (FAKELIGHT_ENABLED)
12325 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12326 else if (rsurface.uselightmaptexture)
12327 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12329 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12330 // then apply the texture to it
12331 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12332 R_Mesh_TexBind(0, layer->texture);
12333 R_Mesh_TexMatrix(0, &layer->texmatrix);
12334 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12335 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12336 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);
12340 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12341 R_Mesh_TexBind(0, layer->texture);
12342 R_Mesh_TexMatrix(0, &layer->texmatrix);
12343 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12344 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12345 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12346 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);
12348 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);
12351 case TEXTURELAYERTYPE_TEXTURE:
12352 // singletexture unlit texture with transparency support
12353 R_Mesh_TexBind(0, layer->texture);
12354 R_Mesh_TexMatrix(0, &layer->texmatrix);
12355 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12356 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12357 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);
12359 case TEXTURELAYERTYPE_FOG:
12360 // singletexture fogging
12361 if (layer->texture)
12363 R_Mesh_TexBind(0, layer->texture);
12364 R_Mesh_TexMatrix(0, &layer->texmatrix);
12365 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12366 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12370 R_Mesh_TexBind(0, 0);
12371 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12373 // generate a color array for the fog pass
12374 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12375 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12379 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12382 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12384 GL_DepthFunc(GL_LEQUAL);
12385 GL_AlphaTest(false);
12389 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12393 r_vertexgeneric_t *batchvertex;
12396 // R_Mesh_ResetTextureState();
12397 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12399 if(rsurface.texture && rsurface.texture->currentskinframe)
12401 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12402 c[3] *= rsurface.texture->currentalpha;
12412 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12414 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12415 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12416 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12419 // brighten it up (as texture value 127 means "unlit")
12420 c[0] *= 2 * r_refdef.view.colorscale;
12421 c[1] *= 2 * r_refdef.view.colorscale;
12422 c[2] *= 2 * r_refdef.view.colorscale;
12424 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12425 c[3] *= r_wateralpha.value;
12427 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12429 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12430 GL_DepthMask(false);
12432 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12434 GL_BlendFunc(GL_ONE, GL_ONE);
12435 GL_DepthMask(false);
12437 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12439 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12440 GL_DepthMask(false);
12442 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12444 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12445 GL_DepthMask(false);
12449 GL_BlendFunc(GL_ONE, GL_ZERO);
12450 GL_DepthMask(writedepth);
12453 if (r_showsurfaces.integer == 3)
12455 rsurface.passcolor4f = NULL;
12457 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12459 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12461 rsurface.passcolor4f = NULL;
12462 rsurface.passcolor4f_vertexbuffer = 0;
12463 rsurface.passcolor4f_bufferoffset = 0;
12465 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12467 qboolean applycolor = true;
12470 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12472 r_refdef.lightmapintensity = 1;
12473 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12474 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12476 else if (FAKELIGHT_ENABLED)
12478 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12480 r_refdef.lightmapintensity = r_fakelight_intensity.value;
12481 RSurf_DrawBatch_GL11_ApplyFakeLight();
12482 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12486 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12488 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12489 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12490 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12493 if(!rsurface.passcolor4f)
12494 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12496 RSurf_DrawBatch_GL11_ApplyAmbient();
12497 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12498 if(r_refdef.fogenabled)
12499 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12500 RSurf_DrawBatch_GL11_ClampColor();
12502 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12503 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12506 else if (!r_refdef.view.showdebug)
12508 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12509 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12510 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12512 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12513 Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12515 R_Mesh_PrepareVertices_Generic_Unlock();
12518 else if (r_showsurfaces.integer == 4)
12520 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12521 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12522 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12524 unsigned char c = vi << 3;
12525 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12526 Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12528 R_Mesh_PrepareVertices_Generic_Unlock();
12531 else if (r_showsurfaces.integer == 2)
12534 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12535 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12536 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12538 unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12539 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12540 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12541 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12542 Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12543 Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12544 Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12546 R_Mesh_PrepareVertices_Generic_Unlock();
12547 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12551 int texturesurfaceindex;
12553 const msurface_t *surface;
12554 unsigned char surfacecolor4ub[4];
12555 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12556 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12558 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12560 surface = texturesurfacelist[texturesurfaceindex];
12561 k = (int)(((size_t)surface) / sizeof(msurface_t));
12562 Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
12563 for (j = 0;j < surface->num_vertices;j++)
12565 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12566 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
12570 R_Mesh_PrepareVertices_Generic_Unlock();
12575 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12578 RSurf_SetupDepthAndCulling();
12579 if (r_showsurfaces.integer)
12581 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12584 switch (vid.renderpath)
12586 case RENDERPATH_GL20:
12587 case RENDERPATH_D3D9:
12588 case RENDERPATH_D3D10:
12589 case RENDERPATH_D3D11:
12590 case RENDERPATH_SOFT:
12591 case RENDERPATH_GLES2:
12592 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12594 case RENDERPATH_GL13:
12595 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12597 case RENDERPATH_GL11:
12598 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12604 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12607 RSurf_SetupDepthAndCulling();
12608 if (r_showsurfaces.integer)
12610 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12613 switch (vid.renderpath)
12615 case RENDERPATH_GL20:
12616 case RENDERPATH_D3D9:
12617 case RENDERPATH_D3D10:
12618 case RENDERPATH_D3D11:
12619 case RENDERPATH_SOFT:
12620 case RENDERPATH_GLES2:
12621 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12623 case RENDERPATH_GL13:
12624 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12626 case RENDERPATH_GL11:
12627 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12633 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12636 int texturenumsurfaces, endsurface;
12637 texture_t *texture;
12638 const msurface_t *surface;
12639 #define MAXBATCH_TRANSPARENTSURFACES 256
12640 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
12642 // if the model is static it doesn't matter what value we give for
12643 // wantnormals and wanttangents, so this logic uses only rules applicable
12644 // to a model, knowing that they are meaningless otherwise
12645 if (ent == r_refdef.scene.worldentity)
12646 RSurf_ActiveWorldEntity();
12647 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12648 RSurf_ActiveModelEntity(ent, false, false, false);
12651 switch (vid.renderpath)
12653 case RENDERPATH_GL20:
12654 case RENDERPATH_D3D9:
12655 case RENDERPATH_D3D10:
12656 case RENDERPATH_D3D11:
12657 case RENDERPATH_SOFT:
12658 case RENDERPATH_GLES2:
12659 RSurf_ActiveModelEntity(ent, true, true, false);
12661 case RENDERPATH_GL13:
12662 case RENDERPATH_GL11:
12663 RSurf_ActiveModelEntity(ent, true, false, false);
12668 if (r_transparentdepthmasking.integer)
12670 qboolean setup = false;
12671 for (i = 0;i < numsurfaces;i = j)
12674 surface = rsurface.modelsurfaces + surfacelist[i];
12675 texture = surface->texture;
12676 rsurface.texture = R_GetCurrentTexture(texture);
12677 rsurface.lightmaptexture = NULL;
12678 rsurface.deluxemaptexture = NULL;
12679 rsurface.uselightmaptexture = false;
12680 // scan ahead until we find a different texture
12681 endsurface = min(i + 1024, numsurfaces);
12682 texturenumsurfaces = 0;
12683 texturesurfacelist[texturenumsurfaces++] = surface;
12684 for (;j < endsurface;j++)
12686 surface = rsurface.modelsurfaces + surfacelist[j];
12687 if (texture != surface->texture)
12689 texturesurfacelist[texturenumsurfaces++] = surface;
12691 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
12693 // render the range of surfaces as depth
12697 GL_ColorMask(0,0,0,0);
12699 GL_DepthTest(true);
12700 GL_BlendFunc(GL_ONE, GL_ZERO);
12701 GL_DepthMask(true);
12702 // R_Mesh_ResetTextureState();
12703 R_SetupShader_DepthOrShadow();
12705 RSurf_SetupDepthAndCulling();
12706 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
12707 if (rsurface.batchvertex3fbuffer)
12708 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12710 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12714 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12717 for (i = 0;i < numsurfaces;i = j)
12720 surface = rsurface.modelsurfaces + surfacelist[i];
12721 texture = surface->texture;
12722 rsurface.texture = R_GetCurrentTexture(texture);
12723 // scan ahead until we find a different texture
12724 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
12725 texturenumsurfaces = 0;
12726 texturesurfacelist[texturenumsurfaces++] = surface;
12727 if(FAKELIGHT_ENABLED)
12729 rsurface.lightmaptexture = NULL;
12730 rsurface.deluxemaptexture = NULL;
12731 rsurface.uselightmaptexture = false;
12732 for (;j < endsurface;j++)
12734 surface = rsurface.modelsurfaces + surfacelist[j];
12735 if (texture != surface->texture)
12737 texturesurfacelist[texturenumsurfaces++] = surface;
12742 rsurface.lightmaptexture = surface->lightmaptexture;
12743 rsurface.deluxemaptexture = surface->deluxemaptexture;
12744 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
12745 for (;j < endsurface;j++)
12747 surface = rsurface.modelsurfaces + surfacelist[j];
12748 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
12750 texturesurfacelist[texturenumsurfaces++] = surface;
12753 // render the range of surfaces
12754 if (ent == r_refdef.scene.worldentity)
12755 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12757 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12759 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12762 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
12764 // transparent surfaces get pushed off into the transparent queue
12765 int surfacelistindex;
12766 const msurface_t *surface;
12767 vec3_t tempcenter, center;
12768 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
12770 surface = texturesurfacelist[surfacelistindex];
12771 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
12772 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
12773 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
12774 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
12775 if (queueentity->transparent_offset) // transparent offset
12777 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
12778 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
12779 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
12781 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
12785 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12787 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
12789 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
12791 RSurf_SetupDepthAndCulling();
12792 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
12793 if (rsurface.batchvertex3fbuffer)
12794 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12796 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12800 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
12802 const entity_render_t *queueentity = r_refdef.scene.worldentity;
12805 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12808 if (!rsurface.texture->currentnumlayers)
12810 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12811 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12813 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12815 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12816 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12817 else if (!rsurface.texture->currentnumlayers)
12819 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12821 // in the deferred case, transparent surfaces were queued during prepass
12822 if (!r_shadow_usingdeferredprepass)
12823 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12827 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12828 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12833 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12836 texture_t *texture;
12837 R_FrameData_SetMark();
12838 // break the surface list down into batches by texture and use of lightmapping
12839 for (i = 0;i < numsurfaces;i = j)
12842 // texture is the base texture pointer, rsurface.texture is the
12843 // current frame/skin the texture is directing us to use (for example
12844 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12845 // use skin 1 instead)
12846 texture = surfacelist[i]->texture;
12847 rsurface.texture = R_GetCurrentTexture(texture);
12848 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12850 // if this texture is not the kind we want, skip ahead to the next one
12851 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12855 if(FAKELIGHT_ENABLED || depthonly || prepass)
12857 rsurface.lightmaptexture = NULL;
12858 rsurface.deluxemaptexture = NULL;
12859 rsurface.uselightmaptexture = false;
12860 // simply scan ahead until we find a different texture or lightmap state
12861 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12866 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12867 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12868 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
12869 // simply scan ahead until we find a different texture or lightmap state
12870 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12873 // render the range of surfaces
12874 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
12876 R_FrameData_ReturnToMark();
12879 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
12883 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12886 if (!rsurface.texture->currentnumlayers)
12888 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12889 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12891 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12893 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12894 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12895 else if (!rsurface.texture->currentnumlayers)
12897 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12899 // in the deferred case, transparent surfaces were queued during prepass
12900 if (!r_shadow_usingdeferredprepass)
12901 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12905 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12906 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12911 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12914 texture_t *texture;
12915 R_FrameData_SetMark();
12916 // break the surface list down into batches by texture and use of lightmapping
12917 for (i = 0;i < numsurfaces;i = j)
12920 // texture is the base texture pointer, rsurface.texture is the
12921 // current frame/skin the texture is directing us to use (for example
12922 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12923 // use skin 1 instead)
12924 texture = surfacelist[i]->texture;
12925 rsurface.texture = R_GetCurrentTexture(texture);
12926 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12928 // if this texture is not the kind we want, skip ahead to the next one
12929 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12933 if(FAKELIGHT_ENABLED || depthonly || prepass)
12935 rsurface.lightmaptexture = NULL;
12936 rsurface.deluxemaptexture = NULL;
12937 rsurface.uselightmaptexture = false;
12938 // simply scan ahead until we find a different texture or lightmap state
12939 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12944 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12945 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12946 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
12947 // simply scan ahead until we find a different texture or lightmap state
12948 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12951 // render the range of surfaces
12952 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
12954 R_FrameData_ReturnToMark();
12957 float locboxvertex3f[6*4*3] =
12959 1,0,1, 1,0,0, 1,1,0, 1,1,1,
12960 0,1,1, 0,1,0, 0,0,0, 0,0,1,
12961 1,1,1, 1,1,0, 0,1,0, 0,1,1,
12962 0,0,1, 0,0,0, 1,0,0, 1,0,1,
12963 0,0,1, 1,0,1, 1,1,1, 0,1,1,
12964 1,0,0, 0,0,0, 0,1,0, 1,1,0
12967 unsigned short locboxelements[6*2*3] =
12972 12,13,14, 12,14,15,
12973 16,17,18, 16,18,19,
12977 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12980 cl_locnode_t *loc = (cl_locnode_t *)ent;
12982 float vertex3f[6*4*3];
12984 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12985 GL_DepthMask(false);
12986 GL_DepthRange(0, 1);
12987 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12988 GL_DepthTest(true);
12989 GL_CullFace(GL_NONE);
12990 R_EntityMatrix(&identitymatrix);
12992 // R_Mesh_ResetTextureState();
12994 i = surfacelist[0];
12995 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12996 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12997 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12998 surfacelist[0] < 0 ? 0.5f : 0.125f);
13000 if (VectorCompare(loc->mins, loc->maxs))
13002 VectorSet(size, 2, 2, 2);
13003 VectorMA(loc->mins, -0.5f, size, mins);
13007 VectorCopy(loc->mins, mins);
13008 VectorSubtract(loc->maxs, loc->mins, size);
13011 for (i = 0;i < 6*4*3;)
13012 for (j = 0;j < 3;j++, i++)
13013 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13015 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13016 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13017 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13020 void R_DrawLocs(void)
13023 cl_locnode_t *loc, *nearestloc;
13025 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13026 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13028 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13029 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13033 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13035 if (decalsystem->decals)
13036 Mem_Free(decalsystem->decals);
13037 memset(decalsystem, 0, sizeof(*decalsystem));
13040 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)
13043 tridecal_t *decals;
13046 // expand or initialize the system
13047 if (decalsystem->maxdecals <= decalsystem->numdecals)
13049 decalsystem_t old = *decalsystem;
13050 qboolean useshortelements;
13051 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13052 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13053 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)));
13054 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13055 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13056 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13057 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13058 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13059 if (decalsystem->numdecals)
13060 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13062 Mem_Free(old.decals);
13063 for (i = 0;i < decalsystem->maxdecals*3;i++)
13064 decalsystem->element3i[i] = i;
13065 if (useshortelements)
13066 for (i = 0;i < decalsystem->maxdecals*3;i++)
13067 decalsystem->element3s[i] = i;
13070 // grab a decal and search for another free slot for the next one
13071 decals = decalsystem->decals;
13072 decal = decalsystem->decals + (i = decalsystem->freedecal++);
13073 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13075 decalsystem->freedecal = i;
13076 if (decalsystem->numdecals <= i)
13077 decalsystem->numdecals = i + 1;
13079 // initialize the decal
13081 decal->triangleindex = triangleindex;
13082 decal->surfaceindex = surfaceindex;
13083 decal->decalsequence = decalsequence;
13084 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13085 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13086 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13087 decal->color4ub[0][3] = 255;
13088 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13089 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13090 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13091 decal->color4ub[1][3] = 255;
13092 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13093 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13094 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13095 decal->color4ub[2][3] = 255;
13096 decal->vertex3f[0][0] = v0[0];
13097 decal->vertex3f[0][1] = v0[1];
13098 decal->vertex3f[0][2] = v0[2];
13099 decal->vertex3f[1][0] = v1[0];
13100 decal->vertex3f[1][1] = v1[1];
13101 decal->vertex3f[1][2] = v1[2];
13102 decal->vertex3f[2][0] = v2[0];
13103 decal->vertex3f[2][1] = v2[1];
13104 decal->vertex3f[2][2] = v2[2];
13105 decal->texcoord2f[0][0] = t0[0];
13106 decal->texcoord2f[0][1] = t0[1];
13107 decal->texcoord2f[1][0] = t1[0];
13108 decal->texcoord2f[1][1] = t1[1];
13109 decal->texcoord2f[2][0] = t2[0];
13110 decal->texcoord2f[2][1] = t2[1];
13113 extern cvar_t cl_decals_bias;
13114 extern cvar_t cl_decals_models;
13115 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13116 // baseparms, parms, temps
13117 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)
13122 const float *vertex3f;
13124 float points[2][9][3];
13131 e = rsurface.modelelement3i + 3*triangleindex;
13133 vertex3f = rsurface.modelvertex3f;
13135 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13137 index = 3*e[cornerindex];
13138 VectorCopy(vertex3f + index, v[cornerindex]);
13141 //TriangleNormal(v[0], v[1], v[2], normal);
13142 //if (DotProduct(normal, localnormal) < 0.0f)
13144 // clip by each of the box planes formed from the projection matrix
13145 // if anything survives, we emit the decal
13146 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]);
13149 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]);
13152 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]);
13155 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]);
13158 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]);
13161 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]);
13164 // some part of the triangle survived, so we have to accept it...
13167 // dynamic always uses the original triangle
13169 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13171 index = 3*e[cornerindex];
13172 VectorCopy(vertex3f + index, v[cornerindex]);
13175 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13177 // convert vertex positions to texcoords
13178 Matrix4x4_Transform(projection, v[cornerindex], temp);
13179 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13180 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13181 // calculate distance fade from the projection origin
13182 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13183 f = bound(0.0f, f, 1.0f);
13184 c[cornerindex][0] = r * f;
13185 c[cornerindex][1] = g * f;
13186 c[cornerindex][2] = b * f;
13187 c[cornerindex][3] = 1.0f;
13188 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13191 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);
13193 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13194 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);
13196 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)
13198 matrix4x4_t projection;
13199 decalsystem_t *decalsystem;
13202 const msurface_t *surface;
13203 const msurface_t *surfaces;
13204 const int *surfacelist;
13205 const texture_t *texture;
13207 int numsurfacelist;
13208 int surfacelistindex;
13211 float localorigin[3];
13212 float localnormal[3];
13213 float localmins[3];
13214 float localmaxs[3];
13217 float planes[6][4];
13220 int bih_triangles_count;
13221 int bih_triangles[256];
13222 int bih_surfaces[256];
13224 decalsystem = &ent->decalsystem;
13225 model = ent->model;
13226 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13228 R_DecalSystem_Reset(&ent->decalsystem);
13232 if (!model->brush.data_leafs && !cl_decals_models.integer)
13234 if (decalsystem->model)
13235 R_DecalSystem_Reset(decalsystem);
13239 if (decalsystem->model != model)
13240 R_DecalSystem_Reset(decalsystem);
13241 decalsystem->model = model;
13243 RSurf_ActiveModelEntity(ent, false, false, false);
13245 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13246 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13247 VectorNormalize(localnormal);
13248 localsize = worldsize*rsurface.inversematrixscale;
13249 localmins[0] = localorigin[0] - localsize;
13250 localmins[1] = localorigin[1] - localsize;
13251 localmins[2] = localorigin[2] - localsize;
13252 localmaxs[0] = localorigin[0] + localsize;
13253 localmaxs[1] = localorigin[1] + localsize;
13254 localmaxs[2] = localorigin[2] + localsize;
13256 //VectorCopy(localnormal, planes[4]);
13257 //VectorVectors(planes[4], planes[2], planes[0]);
13258 AnglesFromVectors(angles, localnormal, NULL, false);
13259 AngleVectors(angles, planes[0], planes[2], planes[4]);
13260 VectorNegate(planes[0], planes[1]);
13261 VectorNegate(planes[2], planes[3]);
13262 VectorNegate(planes[4], planes[5]);
13263 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13264 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13265 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13266 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13267 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13268 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13273 matrix4x4_t forwardprojection;
13274 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13275 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13280 float projectionvector[4][3];
13281 VectorScale(planes[0], ilocalsize, projectionvector[0]);
13282 VectorScale(planes[2], ilocalsize, projectionvector[1]);
13283 VectorScale(planes[4], ilocalsize, projectionvector[2]);
13284 projectionvector[0][0] = planes[0][0] * ilocalsize;
13285 projectionvector[0][1] = planes[1][0] * ilocalsize;
13286 projectionvector[0][2] = planes[2][0] * ilocalsize;
13287 projectionvector[1][0] = planes[0][1] * ilocalsize;
13288 projectionvector[1][1] = planes[1][1] * ilocalsize;
13289 projectionvector[1][2] = planes[2][1] * ilocalsize;
13290 projectionvector[2][0] = planes[0][2] * ilocalsize;
13291 projectionvector[2][1] = planes[1][2] * ilocalsize;
13292 projectionvector[2][2] = planes[2][2] * ilocalsize;
13293 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13294 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13295 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13296 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13300 dynamic = model->surfmesh.isanimated;
13301 numsurfacelist = model->nummodelsurfaces;
13302 surfacelist = model->sortedmodelsurfaces;
13303 surfaces = model->data_surfaces;
13306 bih_triangles_count = -1;
13309 if(model->render_bih.numleafs)
13310 bih = &model->render_bih;
13311 else if(model->collision_bih.numleafs)
13312 bih = &model->collision_bih;
13315 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13316 if(bih_triangles_count == 0)
13318 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13320 if(bih_triangles_count > 0)
13322 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13324 surfaceindex = bih_surfaces[triangleindex];
13325 surface = surfaces + surfaceindex;
13326 texture = surface->texture;
13327 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13329 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13331 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13336 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13338 surfaceindex = surfacelist[surfacelistindex];
13339 surface = surfaces + surfaceindex;
13340 // check cull box first because it rejects more than any other check
13341 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13343 // skip transparent surfaces
13344 texture = surface->texture;
13345 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13347 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13349 numtriangles = surface->num_triangles;
13350 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13351 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13356 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13357 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)
13359 int renderentityindex;
13360 float worldmins[3];
13361 float worldmaxs[3];
13362 entity_render_t *ent;
13364 if (!cl_decals_newsystem.integer)
13367 worldmins[0] = worldorigin[0] - worldsize;
13368 worldmins[1] = worldorigin[1] - worldsize;
13369 worldmins[2] = worldorigin[2] - worldsize;
13370 worldmaxs[0] = worldorigin[0] + worldsize;
13371 worldmaxs[1] = worldorigin[1] + worldsize;
13372 worldmaxs[2] = worldorigin[2] + worldsize;
13374 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13376 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13378 ent = r_refdef.scene.entities[renderentityindex];
13379 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13382 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13386 typedef struct r_decalsystem_splatqueue_s
13388 vec3_t worldorigin;
13389 vec3_t worldnormal;
13395 r_decalsystem_splatqueue_t;
13397 int r_decalsystem_numqueued = 0;
13398 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13400 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)
13402 r_decalsystem_splatqueue_t *queue;
13404 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13407 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13408 VectorCopy(worldorigin, queue->worldorigin);
13409 VectorCopy(worldnormal, queue->worldnormal);
13410 Vector4Set(queue->color, r, g, b, a);
13411 Vector4Set(queue->tcrange, s1, t1, s2, t2);
13412 queue->worldsize = worldsize;
13413 queue->decalsequence = cl.decalsequence++;
13416 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13419 r_decalsystem_splatqueue_t *queue;
13421 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13422 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);
13423 r_decalsystem_numqueued = 0;
13426 extern cvar_t cl_decals_max;
13427 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13430 decalsystem_t *decalsystem = &ent->decalsystem;
13437 if (!decalsystem->numdecals)
13440 if (r_showsurfaces.integer)
13443 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13445 R_DecalSystem_Reset(decalsystem);
13449 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13450 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13452 if (decalsystem->lastupdatetime)
13453 frametime = (cl.time - decalsystem->lastupdatetime);
13456 decalsystem->lastupdatetime = cl.time;
13457 decal = decalsystem->decals;
13458 numdecals = decalsystem->numdecals;
13460 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13462 if (decal->color4ub[0][3])
13464 decal->lived += frametime;
13465 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13467 memset(decal, 0, sizeof(*decal));
13468 if (decalsystem->freedecal > i)
13469 decalsystem->freedecal = i;
13473 decal = decalsystem->decals;
13474 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13477 // collapse the array by shuffling the tail decals into the gaps
13480 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13481 decalsystem->freedecal++;
13482 if (decalsystem->freedecal == numdecals)
13484 decal[decalsystem->freedecal] = decal[--numdecals];
13487 decalsystem->numdecals = numdecals;
13489 if (numdecals <= 0)
13491 // if there are no decals left, reset decalsystem
13492 R_DecalSystem_Reset(decalsystem);
13496 extern skinframe_t *decalskinframe;
13497 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13500 decalsystem_t *decalsystem = &ent->decalsystem;
13509 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13512 numdecals = decalsystem->numdecals;
13516 if (r_showsurfaces.integer)
13519 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13521 R_DecalSystem_Reset(decalsystem);
13525 // if the model is static it doesn't matter what value we give for
13526 // wantnormals and wanttangents, so this logic uses only rules applicable
13527 // to a model, knowing that they are meaningless otherwise
13528 if (ent == r_refdef.scene.worldentity)
13529 RSurf_ActiveWorldEntity();
13531 RSurf_ActiveModelEntity(ent, false, false, false);
13533 decalsystem->lastupdatetime = cl.time;
13534 decal = decalsystem->decals;
13536 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13538 // update vertex positions for animated models
13539 v3f = decalsystem->vertex3f;
13540 c4f = decalsystem->color4f;
13541 t2f = decalsystem->texcoord2f;
13542 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13544 if (!decal->color4ub[0][3])
13547 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13550 // update color values for fading decals
13551 if (decal->lived >= cl_decals_time.value)
13553 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13554 alpha *= (1.0f/255.0f);
13557 alpha = 1.0f/255.0f;
13559 c4f[ 0] = decal->color4ub[0][0] * alpha;
13560 c4f[ 1] = decal->color4ub[0][1] * alpha;
13561 c4f[ 2] = decal->color4ub[0][2] * alpha;
13563 c4f[ 4] = decal->color4ub[1][0] * alpha;
13564 c4f[ 5] = decal->color4ub[1][1] * alpha;
13565 c4f[ 6] = decal->color4ub[1][2] * alpha;
13567 c4f[ 8] = decal->color4ub[2][0] * alpha;
13568 c4f[ 9] = decal->color4ub[2][1] * alpha;
13569 c4f[10] = decal->color4ub[2][2] * alpha;
13572 t2f[0] = decal->texcoord2f[0][0];
13573 t2f[1] = decal->texcoord2f[0][1];
13574 t2f[2] = decal->texcoord2f[1][0];
13575 t2f[3] = decal->texcoord2f[1][1];
13576 t2f[4] = decal->texcoord2f[2][0];
13577 t2f[5] = decal->texcoord2f[2][1];
13579 // update vertex positions for animated models
13580 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13582 e = rsurface.modelelement3i + 3*decal->triangleindex;
13583 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
13584 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
13585 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
13589 VectorCopy(decal->vertex3f[0], v3f);
13590 VectorCopy(decal->vertex3f[1], v3f + 3);
13591 VectorCopy(decal->vertex3f[2], v3f + 6);
13594 if (r_refdef.fogenabled)
13596 alpha = RSurf_FogVertex(v3f);
13597 VectorScale(c4f, alpha, c4f);
13598 alpha = RSurf_FogVertex(v3f + 3);
13599 VectorScale(c4f + 4, alpha, c4f + 4);
13600 alpha = RSurf_FogVertex(v3f + 6);
13601 VectorScale(c4f + 8, alpha, c4f + 8);
13612 r_refdef.stats.drawndecals += numtris;
13614 // now render the decals all at once
13615 // (this assumes they all use one particle font texture!)
13616 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);
13617 // R_Mesh_ResetTextureState();
13618 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
13619 GL_DepthMask(false);
13620 GL_DepthRange(0, 1);
13621 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
13622 GL_DepthTest(true);
13623 GL_CullFace(GL_NONE);
13624 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
13625 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
13626 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
13630 static void R_DrawModelDecals(void)
13634 // fade faster when there are too many decals
13635 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13636 for (i = 0;i < r_refdef.scene.numentities;i++)
13637 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13639 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
13640 for (i = 0;i < r_refdef.scene.numentities;i++)
13641 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13642 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
13644 R_DecalSystem_ApplySplatEntitiesQueue();
13646 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13647 for (i = 0;i < r_refdef.scene.numentities;i++)
13648 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13650 r_refdef.stats.totaldecals += numdecals;
13652 if (r_showsurfaces.integer)
13655 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
13657 for (i = 0;i < r_refdef.scene.numentities;i++)
13659 if (!r_refdef.viewcache.entityvisible[i])
13661 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13662 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
13666 extern cvar_t mod_collision_bih;
13667 void R_DrawDebugModel(void)
13669 entity_render_t *ent = rsurface.entity;
13670 int i, j, k, l, flagsmask;
13671 const msurface_t *surface;
13672 dp_model_t *model = ent->model;
13675 switch(vid.renderpath)
13677 case RENDERPATH_GL11:
13678 case RENDERPATH_GL13:
13679 case RENDERPATH_GL20:
13681 case RENDERPATH_D3D9:
13682 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13684 case RENDERPATH_D3D10:
13685 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13687 case RENDERPATH_D3D11:
13688 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13690 case RENDERPATH_SOFT:
13691 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13693 case RENDERPATH_GLES2:
13694 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13698 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
13700 // R_Mesh_ResetTextureState();
13701 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13702 GL_DepthRange(0, 1);
13703 GL_DepthTest(!r_showdisabledepthtest.integer);
13704 GL_DepthMask(false);
13705 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13707 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
13711 qboolean cullbox = ent == r_refdef.scene.worldentity;
13712 const q3mbrush_t *brush;
13713 const bih_t *bih = &model->collision_bih;
13714 const bih_leaf_t *bihleaf;
13715 float vertex3f[3][3];
13716 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
13718 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
13720 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
13722 switch (bihleaf->type)
13725 brush = model->brush.data_brushes + bihleaf->itemindex;
13726 if (brush->colbrushf && brush->colbrushf->numtriangles)
13728 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);
13729 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
13730 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
13733 case BIH_COLLISIONTRIANGLE:
13734 triangleindex = bihleaf->itemindex;
13735 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
13736 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
13737 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
13738 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);
13739 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13740 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13742 case BIH_RENDERTRIANGLE:
13743 triangleindex = bihleaf->itemindex;
13744 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
13745 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
13746 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
13747 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);
13748 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13749 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13755 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13757 if (r_showtris.integer || (r_shownormals.value != 0))
13759 if (r_showdisabledepthtest.integer)
13761 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13762 GL_DepthMask(false);
13766 GL_BlendFunc(GL_ONE, GL_ZERO);
13767 GL_DepthMask(true);
13769 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
13771 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
13773 rsurface.texture = R_GetCurrentTexture(surface->texture);
13774 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
13776 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
13777 if (r_showtris.value > 0)
13779 if (!rsurface.texture->currentlayers->depthmask)
13780 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
13781 else if (ent == r_refdef.scene.worldentity)
13782 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
13784 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
13785 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
13786 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
13788 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
13791 if (r_shownormals.value < 0)
13793 qglBegin(GL_LINES);
13794 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13796 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13797 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13798 qglVertex3f(v[0], v[1], v[2]);
13799 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
13800 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13801 qglVertex3f(v[0], v[1], v[2]);
13806 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
13808 qglBegin(GL_LINES);
13809 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13811 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13812 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13813 qglVertex3f(v[0], v[1], v[2]);
13814 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
13815 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13816 qglVertex3f(v[0], v[1], v[2]);
13820 qglBegin(GL_LINES);
13821 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13823 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13824 GL_Color(0, r_refdef.view.colorscale, 0, 1);
13825 qglVertex3f(v[0], v[1], v[2]);
13826 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
13827 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13828 qglVertex3f(v[0], v[1], v[2]);
13832 qglBegin(GL_LINES);
13833 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13835 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13836 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13837 qglVertex3f(v[0], v[1], v[2]);
13838 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
13839 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13840 qglVertex3f(v[0], v[1], v[2]);
13847 rsurface.texture = NULL;
13851 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
13852 int r_maxsurfacelist = 0;
13853 const msurface_t **r_surfacelist = NULL;
13854 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13856 int i, j, endj, flagsmask;
13857 dp_model_t *model = r_refdef.scene.worldmodel;
13858 msurface_t *surfaces;
13859 unsigned char *update;
13860 int numsurfacelist = 0;
13864 if (r_maxsurfacelist < model->num_surfaces)
13866 r_maxsurfacelist = model->num_surfaces;
13868 Mem_Free((msurface_t**)r_surfacelist);
13869 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13872 RSurf_ActiveWorldEntity();
13874 surfaces = model->data_surfaces;
13875 update = model->brushq1.lightmapupdateflags;
13877 // update light styles on this submodel
13878 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13880 model_brush_lightstyleinfo_t *style;
13881 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13883 if (style->value != r_refdef.scene.lightstylevalue[style->style])
13885 int *list = style->surfacelist;
13886 style->value = r_refdef.scene.lightstylevalue[style->style];
13887 for (j = 0;j < style->numsurfaces;j++)
13888 update[list[j]] = true;
13893 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13897 R_DrawDebugModel();
13898 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13902 rsurface.lightmaptexture = NULL;
13903 rsurface.deluxemaptexture = NULL;
13904 rsurface.uselightmaptexture = false;
13905 rsurface.texture = NULL;
13906 rsurface.rtlight = NULL;
13907 numsurfacelist = 0;
13908 // add visible surfaces to draw list
13909 for (i = 0;i < model->nummodelsurfaces;i++)
13911 j = model->sortedmodelsurfaces[i];
13912 if (r_refdef.viewcache.world_surfacevisible[j])
13913 r_surfacelist[numsurfacelist++] = surfaces + j;
13915 // update lightmaps if needed
13916 if (model->brushq1.firstrender)
13918 model->brushq1.firstrender = false;
13919 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13921 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13925 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13926 if (r_refdef.viewcache.world_surfacevisible[j])
13928 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13930 // don't do anything if there were no surfaces
13931 if (!numsurfacelist)
13933 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13936 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13938 // add to stats if desired
13939 if (r_speeds.integer && !skysurfaces && !depthonly)
13941 r_refdef.stats.world_surfaces += numsurfacelist;
13942 for (j = 0;j < numsurfacelist;j++)
13943 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
13946 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13949 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13951 int i, j, endj, flagsmask;
13952 dp_model_t *model = ent->model;
13953 msurface_t *surfaces;
13954 unsigned char *update;
13955 int numsurfacelist = 0;
13959 if (r_maxsurfacelist < model->num_surfaces)
13961 r_maxsurfacelist = model->num_surfaces;
13963 Mem_Free((msurface_t **)r_surfacelist);
13964 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13967 // if the model is static it doesn't matter what value we give for
13968 // wantnormals and wanttangents, so this logic uses only rules applicable
13969 // to a model, knowing that they are meaningless otherwise
13970 if (ent == r_refdef.scene.worldentity)
13971 RSurf_ActiveWorldEntity();
13972 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13973 RSurf_ActiveModelEntity(ent, false, false, false);
13975 RSurf_ActiveModelEntity(ent, true, true, true);
13976 else if (depthonly)
13978 switch (vid.renderpath)
13980 case RENDERPATH_GL20:
13981 case RENDERPATH_D3D9:
13982 case RENDERPATH_D3D10:
13983 case RENDERPATH_D3D11:
13984 case RENDERPATH_SOFT:
13985 case RENDERPATH_GLES2:
13986 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
13988 case RENDERPATH_GL13:
13989 case RENDERPATH_GL11:
13990 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
13996 switch (vid.renderpath)
13998 case RENDERPATH_GL20:
13999 case RENDERPATH_D3D9:
14000 case RENDERPATH_D3D10:
14001 case RENDERPATH_D3D11:
14002 case RENDERPATH_SOFT:
14003 case RENDERPATH_GLES2:
14004 RSurf_ActiveModelEntity(ent, true, true, false);
14006 case RENDERPATH_GL13:
14007 case RENDERPATH_GL11:
14008 RSurf_ActiveModelEntity(ent, true, false, false);
14013 surfaces = model->data_surfaces;
14014 update = model->brushq1.lightmapupdateflags;
14016 // update light styles
14017 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14019 model_brush_lightstyleinfo_t *style;
14020 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14022 if (style->value != r_refdef.scene.lightstylevalue[style->style])
14024 int *list = style->surfacelist;
14025 style->value = r_refdef.scene.lightstylevalue[style->style];
14026 for (j = 0;j < style->numsurfaces;j++)
14027 update[list[j]] = true;
14032 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14036 R_DrawDebugModel();
14037 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14041 rsurface.lightmaptexture = NULL;
14042 rsurface.deluxemaptexture = NULL;
14043 rsurface.uselightmaptexture = false;
14044 rsurface.texture = NULL;
14045 rsurface.rtlight = NULL;
14046 numsurfacelist = 0;
14047 // add visible surfaces to draw list
14048 for (i = 0;i < model->nummodelsurfaces;i++)
14049 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14050 // don't do anything if there were no surfaces
14051 if (!numsurfacelist)
14053 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14056 // update lightmaps if needed
14060 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14065 R_BuildLightMap(ent, surfaces + j);
14070 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14072 R_BuildLightMap(ent, surfaces + j);
14073 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14075 // add to stats if desired
14076 if (r_speeds.integer && !skysurfaces && !depthonly)
14078 r_refdef.stats.entities_surfaces += numsurfacelist;
14079 for (j = 0;j < numsurfacelist;j++)
14080 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14083 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14086 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14088 static texture_t texture;
14089 static msurface_t surface;
14090 const msurface_t *surfacelist = &surface;
14092 // fake enough texture and surface state to render this geometry
14094 texture.update_lastrenderframe = -1; // regenerate this texture
14095 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14096 texture.currentskinframe = skinframe;
14097 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14098 texture.offsetmapping = OFFSETMAPPING_OFF;
14099 texture.offsetscale = 1;
14100 texture.specularscalemod = 1;
14101 texture.specularpowermod = 1;
14103 surface.texture = &texture;
14104 surface.num_triangles = numtriangles;
14105 surface.num_firsttriangle = firsttriangle;
14106 surface.num_vertices = numvertices;
14107 surface.num_firstvertex = firstvertex;
14110 rsurface.texture = R_GetCurrentTexture(surface.texture);
14111 rsurface.lightmaptexture = NULL;
14112 rsurface.deluxemaptexture = NULL;
14113 rsurface.uselightmaptexture = false;
14114 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14117 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)
14119 static msurface_t surface;
14120 const msurface_t *surfacelist = &surface;
14122 // fake enough texture and surface state to render this geometry
14123 surface.texture = texture;
14124 surface.num_triangles = numtriangles;
14125 surface.num_firsttriangle = firsttriangle;
14126 surface.num_vertices = numvertices;
14127 surface.num_firstvertex = firstvertex;
14130 rsurface.texture = R_GetCurrentTexture(surface.texture);
14131 rsurface.lightmaptexture = NULL;
14132 rsurface.deluxemaptexture = NULL;
14133 rsurface.uselightmaptexture = false;
14134 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);