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, FOGWIDTH, 1);
516 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 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"},
3443 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3444 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3446 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3447 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3448 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3449 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3450 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3451 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3452 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3453 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3454 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3455 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3456 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3457 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3458 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3459 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3460 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3461 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3462 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDBOUNCELIGHT\n", " deferredbouncelight"},
3465 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3467 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3468 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3469 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3470 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3471 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3472 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3473 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3474 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3475 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3476 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3477 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3478 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3479 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3480 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3481 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3482 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3483 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDBOUNCELIGHT\n", " deferredbouncelight"},
3486 struct r_glsl_permutation_s;
3487 typedef struct r_glsl_permutation_s
3489 /// hash lookup data
3490 struct r_glsl_permutation_s *hashnext;
3492 unsigned int permutation;
3494 /// indicates if we have tried compiling this permutation already
3496 /// 0 if compilation failed
3498 // texture units assigned to each detected uniform
3499 int tex_Texture_First;
3500 int tex_Texture_Second;
3501 int tex_Texture_GammaRamps;
3502 int tex_Texture_Normal;
3503 int tex_Texture_Color;
3504 int tex_Texture_Gloss;
3505 int tex_Texture_Glow;
3506 int tex_Texture_SecondaryNormal;
3507 int tex_Texture_SecondaryColor;
3508 int tex_Texture_SecondaryGloss;
3509 int tex_Texture_SecondaryGlow;
3510 int tex_Texture_Pants;
3511 int tex_Texture_Shirt;
3512 int tex_Texture_FogHeightTexture;
3513 int tex_Texture_FogMask;
3514 int tex_Texture_Lightmap;
3515 int tex_Texture_Deluxemap;
3516 int tex_Texture_Attenuation;
3517 int tex_Texture_Cube;
3518 int tex_Texture_Refraction;
3519 int tex_Texture_Reflection;
3520 int tex_Texture_ShadowMap2D;
3521 int tex_Texture_CubeProjection;
3522 int tex_Texture_ScreenDepth;
3523 int tex_Texture_ScreenNormalMap;
3524 int tex_Texture_ScreenDiffuse;
3525 int tex_Texture_ScreenSpecular;
3526 int tex_Texture_ReflectMask;
3527 int tex_Texture_ReflectCube;
3528 /// locations of detected uniforms in program object, or -1 if not found
3529 int loc_Texture_First;
3530 int loc_Texture_Second;
3531 int loc_Texture_GammaRamps;
3532 int loc_Texture_Normal;
3533 int loc_Texture_Color;
3534 int loc_Texture_Gloss;
3535 int loc_Texture_Glow;
3536 int loc_Texture_SecondaryNormal;
3537 int loc_Texture_SecondaryColor;
3538 int loc_Texture_SecondaryGloss;
3539 int loc_Texture_SecondaryGlow;
3540 int loc_Texture_Pants;
3541 int loc_Texture_Shirt;
3542 int loc_Texture_FogHeightTexture;
3543 int loc_Texture_FogMask;
3544 int loc_Texture_Lightmap;
3545 int loc_Texture_Deluxemap;
3546 int loc_Texture_Attenuation;
3547 int loc_Texture_Cube;
3548 int loc_Texture_Refraction;
3549 int loc_Texture_Reflection;
3550 int loc_Texture_ShadowMap2D;
3551 int loc_Texture_CubeProjection;
3552 int loc_Texture_ScreenDepth;
3553 int loc_Texture_ScreenNormalMap;
3554 int loc_Texture_ScreenDiffuse;
3555 int loc_Texture_ScreenSpecular;
3556 int loc_Texture_ReflectMask;
3557 int loc_Texture_ReflectCube;
3559 int loc_BloomBlur_Parameters;
3561 int loc_Color_Ambient;
3562 int loc_Color_Diffuse;
3563 int loc_Color_Specular;
3565 int loc_Color_Pants;
3566 int loc_Color_Shirt;
3567 int loc_DeferredColor_Ambient;
3568 int loc_DeferredColor_Diffuse;
3569 int loc_DeferredColor_Specular;
3570 int loc_DeferredMod_Diffuse;
3571 int loc_DeferredMod_Specular;
3572 int loc_DistortScaleRefractReflect;
3573 int loc_EyePosition;
3575 int loc_FogHeightFade;
3577 int loc_FogPlaneViewDist;
3578 int loc_FogRangeRecip;
3581 int loc_LightPosition;
3582 int loc_OffsetMapping_Scale;
3584 int loc_ReflectColor;
3585 int loc_ReflectFactor;
3586 int loc_ReflectOffset;
3587 int loc_RefractColor;
3589 int loc_ScreenCenterRefractReflect;
3590 int loc_ScreenScaleRefractReflect;
3591 int loc_ScreenToDepth;
3592 int loc_ShadowMap_Parameters;
3593 int loc_ShadowMap_TextureScale;
3594 int loc_SpecularPower;
3599 int loc_ViewTintColor;
3600 int loc_ViewToLight;
3601 int loc_ModelToLight;
3603 int loc_BackgroundTexMatrix;
3604 int loc_ModelViewProjectionMatrix;
3605 int loc_ModelViewMatrix;
3606 int loc_PixelToScreenTexCoord;
3607 int loc_ModelToReflectCube;
3608 int loc_ShadowMapMatrix;
3609 int loc_BloomColorSubtract;
3610 int loc_NormalmapScrollBlend;
3612 r_glsl_permutation_t;
3614 #define SHADERPERMUTATION_HASHSIZE 256
3617 // non-degradable "lightweight" shader parameters to keep the permutations simpler
3618 // these can NOT degrade! only use for simple stuff
3621 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
3622 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3623 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
3624 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
3625 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
3626 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5 ///< postprocess uservec4 is enabled
3628 #define SHADERSTATICPARMS_COUNT 6
3630 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
3631 static int shaderstaticparms_count = 0;
3633 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
3634 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
3635 qboolean R_CompileShader_CheckStaticParms(void)
3637 static int r_compileshader_staticparms_save[1];
3638 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
3639 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
3642 if (r_glsl_saturation_redcompensate.integer)
3643 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
3644 if (r_shadow_glossexact.integer)
3645 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
3646 if (r_glsl_postprocess.integer)
3648 if (r_glsl_postprocess_uservec1_enable.integer)
3649 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
3650 if (r_glsl_postprocess_uservec2_enable.integer)
3651 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
3652 if (r_glsl_postprocess_uservec3_enable.integer)
3653 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
3654 if (r_glsl_postprocess_uservec4_enable.integer)
3655 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
3657 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
3660 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
3661 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
3662 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
3664 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
3665 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
3667 shaderstaticparms_count = 0;
3670 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
3671 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
3672 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
3673 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
3674 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
3675 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
3678 /// information about each possible shader permutation
3679 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3680 /// currently selected permutation
3681 r_glsl_permutation_t *r_glsl_permutation;
3682 /// storage for permutations linked in the hash table
3683 memexpandablearray_t r_glsl_permutationarray;
3685 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3687 //unsigned int hashdepth = 0;
3688 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3689 r_glsl_permutation_t *p;
3690 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3692 if (p->mode == mode && p->permutation == permutation)
3694 //if (hashdepth > 10)
3695 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3700 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3702 p->permutation = permutation;
3703 p->hashnext = r_glsl_permutationhash[mode][hashindex];
3704 r_glsl_permutationhash[mode][hashindex] = p;
3705 //if (hashdepth > 10)
3706 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3710 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3713 if (!filename || !filename[0])
3715 if (!strcmp(filename, "glsl/default.glsl"))
3717 if (!glslshaderstring)
3719 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3720 if (glslshaderstring)
3721 Con_DPrintf("Loading shaders from file %s...\n", filename);
3723 glslshaderstring = (char *)builtinshaderstring;
3725 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3726 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3727 return shaderstring;
3729 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3732 if (printfromdisknotice)
3733 Con_DPrintf("from disk %s... ", filename);
3734 return shaderstring;
3736 return shaderstring;
3739 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3743 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3744 char *vertexstring, *geometrystring, *fragmentstring;
3745 char permutationname[256];
3746 int vertstrings_count = 0;
3747 int geomstrings_count = 0;
3748 int fragstrings_count = 0;
3749 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3750 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3751 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3758 permutationname[0] = 0;
3759 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
3760 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3761 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3763 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3765 // the first pretext is which type of shader to compile as
3766 // (later these will all be bound together as a program object)
3767 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3768 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3769 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3771 // the second pretext is the mode (for example a light source)
3772 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3773 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3774 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3775 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3777 // now add all the permutation pretexts
3778 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3780 if (permutation & (1<<i))
3782 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3783 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3784 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3785 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3789 // keep line numbers correct
3790 vertstrings_list[vertstrings_count++] = "\n";
3791 geomstrings_list[geomstrings_count++] = "\n";
3792 fragstrings_list[fragstrings_count++] = "\n";
3797 R_CompileShader_AddStaticParms(mode, permutation);
3798 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3799 vertstrings_count += shaderstaticparms_count;
3800 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3801 geomstrings_count += shaderstaticparms_count;
3802 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3803 fragstrings_count += shaderstaticparms_count;
3805 // now append the shader text itself
3806 vertstrings_list[vertstrings_count++] = vertexstring;
3807 geomstrings_list[geomstrings_count++] = geometrystring;
3808 fragstrings_list[fragstrings_count++] = fragmentstring;
3810 // if any sources were NULL, clear the respective list
3812 vertstrings_count = 0;
3813 if (!geometrystring)
3814 geomstrings_count = 0;
3815 if (!fragmentstring)
3816 fragstrings_count = 0;
3818 // compile the shader program
3819 if (vertstrings_count + geomstrings_count + fragstrings_count)
3820 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3824 qglUseProgram(p->program);CHECKGLERROR
3825 // look up all the uniform variable names we care about, so we don't
3826 // have to look them up every time we set them
3828 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
3829 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
3830 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
3831 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
3832 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
3833 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
3834 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
3835 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
3836 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
3837 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
3838 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
3839 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
3840 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
3841 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
3842 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
3843 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
3844 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
3845 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
3846 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
3847 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
3848 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
3849 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
3850 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
3851 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
3852 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
3853 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
3854 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
3855 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
3856 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
3857 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
3858 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
3859 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
3860 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
3861 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
3862 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
3863 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
3864 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
3865 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
3866 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
3867 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
3868 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
3869 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
3870 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
3871 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
3872 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
3873 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
3874 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
3875 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
3876 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
3877 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
3878 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
3879 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
3880 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
3881 p->loc_OffsetMapping_Scale = qglGetUniformLocation(p->program, "OffsetMapping_Scale");
3882 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
3883 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
3884 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
3885 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
3886 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
3887 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
3888 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
3889 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
3890 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
3891 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
3892 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
3893 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
3894 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
3895 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
3896 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
3897 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
3898 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
3899 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
3900 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
3901 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
3902 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
3903 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
3904 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
3905 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
3906 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
3907 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
3908 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
3909 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
3910 // initialize the samplers to refer to the texture units we use
3911 p->tex_Texture_First = -1;
3912 p->tex_Texture_Second = -1;
3913 p->tex_Texture_GammaRamps = -1;
3914 p->tex_Texture_Normal = -1;
3915 p->tex_Texture_Color = -1;
3916 p->tex_Texture_Gloss = -1;
3917 p->tex_Texture_Glow = -1;
3918 p->tex_Texture_SecondaryNormal = -1;
3919 p->tex_Texture_SecondaryColor = -1;
3920 p->tex_Texture_SecondaryGloss = -1;
3921 p->tex_Texture_SecondaryGlow = -1;
3922 p->tex_Texture_Pants = -1;
3923 p->tex_Texture_Shirt = -1;
3924 p->tex_Texture_FogHeightTexture = -1;
3925 p->tex_Texture_FogMask = -1;
3926 p->tex_Texture_Lightmap = -1;
3927 p->tex_Texture_Deluxemap = -1;
3928 p->tex_Texture_Attenuation = -1;
3929 p->tex_Texture_Cube = -1;
3930 p->tex_Texture_Refraction = -1;
3931 p->tex_Texture_Reflection = -1;
3932 p->tex_Texture_ShadowMap2D = -1;
3933 p->tex_Texture_CubeProjection = -1;
3934 p->tex_Texture_ScreenDepth = -1;
3935 p->tex_Texture_ScreenNormalMap = -1;
3936 p->tex_Texture_ScreenDiffuse = -1;
3937 p->tex_Texture_ScreenSpecular = -1;
3938 p->tex_Texture_ReflectMask = -1;
3939 p->tex_Texture_ReflectCube = -1;
3941 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
3942 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
3943 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
3944 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
3945 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
3946 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
3947 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
3948 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
3949 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
3950 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
3951 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
3952 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
3953 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
3954 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
3955 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
3956 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
3957 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
3958 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
3959 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
3960 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
3961 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
3962 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
3963 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
3964 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
3965 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
3966 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
3967 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
3968 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
3969 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
3971 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
3974 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
3978 Mem_Free(vertexstring);
3980 Mem_Free(geometrystring);
3982 Mem_Free(fragmentstring);
3985 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3987 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3988 if (r_glsl_permutation != perm)
3990 r_glsl_permutation = perm;
3991 if (!r_glsl_permutation->program)
3993 if (!r_glsl_permutation->compiled)
3994 R_GLSL_CompilePermutation(perm, mode, permutation);
3995 if (!r_glsl_permutation->program)
3997 // remove features until we find a valid permutation
3999 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4001 // reduce i more quickly whenever it would not remove any bits
4002 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4003 if (!(permutation & j))
4006 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
4007 if (!r_glsl_permutation->compiled)
4008 R_GLSL_CompilePermutation(perm, mode, permutation);
4009 if (r_glsl_permutation->program)
4012 if (i >= SHADERPERMUTATION_COUNT)
4014 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4015 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
4016 qglUseProgram(0);CHECKGLERROR
4017 return; // no bit left to clear, entire mode is broken
4022 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
4024 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
4025 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
4026 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
4033 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4034 extern D3DCAPS9 vid_d3d9caps;
4037 struct r_hlsl_permutation_s;
4038 typedef struct r_hlsl_permutation_s
4040 /// hash lookup data
4041 struct r_hlsl_permutation_s *hashnext;
4043 unsigned int permutation;
4045 /// indicates if we have tried compiling this permutation already
4047 /// NULL if compilation failed
4048 IDirect3DVertexShader9 *vertexshader;
4049 IDirect3DPixelShader9 *pixelshader;
4051 r_hlsl_permutation_t;
4053 typedef enum D3DVSREGISTER_e
4055 D3DVSREGISTER_TexMatrix = 0, // float4x4
4056 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4057 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4058 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4059 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4060 D3DVSREGISTER_ModelToLight = 20, // float4x4
4061 D3DVSREGISTER_EyePosition = 24,
4062 D3DVSREGISTER_FogPlane = 25,
4063 D3DVSREGISTER_LightDir = 26,
4064 D3DVSREGISTER_LightPosition = 27,
4068 typedef enum D3DPSREGISTER_e
4070 D3DPSREGISTER_Alpha = 0,
4071 D3DPSREGISTER_BloomBlur_Parameters = 1,
4072 D3DPSREGISTER_ClientTime = 2,
4073 D3DPSREGISTER_Color_Ambient = 3,
4074 D3DPSREGISTER_Color_Diffuse = 4,
4075 D3DPSREGISTER_Color_Specular = 5,
4076 D3DPSREGISTER_Color_Glow = 6,
4077 D3DPSREGISTER_Color_Pants = 7,
4078 D3DPSREGISTER_Color_Shirt = 8,
4079 D3DPSREGISTER_DeferredColor_Ambient = 9,
4080 D3DPSREGISTER_DeferredColor_Diffuse = 10,
4081 D3DPSREGISTER_DeferredColor_Specular = 11,
4082 D3DPSREGISTER_DeferredMod_Diffuse = 12,
4083 D3DPSREGISTER_DeferredMod_Specular = 13,
4084 D3DPSREGISTER_DistortScaleRefractReflect = 14,
4085 D3DPSREGISTER_EyePosition = 15, // unused
4086 D3DPSREGISTER_FogColor = 16,
4087 D3DPSREGISTER_FogHeightFade = 17,
4088 D3DPSREGISTER_FogPlane = 18,
4089 D3DPSREGISTER_FogPlaneViewDist = 19,
4090 D3DPSREGISTER_FogRangeRecip = 20,
4091 D3DPSREGISTER_LightColor = 21,
4092 D3DPSREGISTER_LightDir = 22, // unused
4093 D3DPSREGISTER_LightPosition = 23,
4094 D3DPSREGISTER_OffsetMapping_Scale = 24,
4095 D3DPSREGISTER_PixelSize = 25,
4096 D3DPSREGISTER_ReflectColor = 26,
4097 D3DPSREGISTER_ReflectFactor = 27,
4098 D3DPSREGISTER_ReflectOffset = 28,
4099 D3DPSREGISTER_RefractColor = 29,
4100 D3DPSREGISTER_Saturation = 30,
4101 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4102 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4103 D3DPSREGISTER_ScreenToDepth = 33,
4104 D3DPSREGISTER_ShadowMap_Parameters = 34,
4105 D3DPSREGISTER_ShadowMap_TextureScale = 35,
4106 D3DPSREGISTER_SpecularPower = 36,
4107 D3DPSREGISTER_UserVec1 = 37,
4108 D3DPSREGISTER_UserVec2 = 38,
4109 D3DPSREGISTER_UserVec3 = 39,
4110 D3DPSREGISTER_UserVec4 = 40,
4111 D3DPSREGISTER_ViewTintColor = 41,
4112 D3DPSREGISTER_PixelToScreenTexCoord = 42,
4113 D3DPSREGISTER_BloomColorSubtract = 43,
4114 D3DPSREGISTER_ViewToLight = 44, // float4x4
4115 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4116 D3DPSREGISTER_NormalmapScrollBlend = 52,
4121 /// information about each possible shader permutation
4122 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4123 /// currently selected permutation
4124 r_hlsl_permutation_t *r_hlsl_permutation;
4125 /// storage for permutations linked in the hash table
4126 memexpandablearray_t r_hlsl_permutationarray;
4128 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4130 //unsigned int hashdepth = 0;
4131 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4132 r_hlsl_permutation_t *p;
4133 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4135 if (p->mode == mode && p->permutation == permutation)
4137 //if (hashdepth > 10)
4138 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4143 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4145 p->permutation = permutation;
4146 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4147 r_hlsl_permutationhash[mode][hashindex] = p;
4148 //if (hashdepth > 10)
4149 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4153 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4156 if (!filename || !filename[0])
4158 if (!strcmp(filename, "hlsl/default.hlsl"))
4160 if (!hlslshaderstring)
4162 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4163 if (hlslshaderstring)
4164 Con_DPrintf("Loading shaders from file %s...\n", filename);
4166 hlslshaderstring = (char *)builtinhlslshaderstring;
4168 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4169 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4170 return shaderstring;
4172 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4175 if (printfromdisknotice)
4176 Con_DPrintf("from disk %s... ", filename);
4177 return shaderstring;
4179 return shaderstring;
4183 //#include <d3dx9shader.h>
4184 //#include <d3dx9mesh.h>
4186 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4188 DWORD *vsbin = NULL;
4189 DWORD *psbin = NULL;
4190 fs_offset_t vsbinsize;
4191 fs_offset_t psbinsize;
4192 // IDirect3DVertexShader9 *vs = NULL;
4193 // IDirect3DPixelShader9 *ps = NULL;
4194 ID3DXBuffer *vslog = NULL;
4195 ID3DXBuffer *vsbuffer = NULL;
4196 ID3DXConstantTable *vsconstanttable = NULL;
4197 ID3DXBuffer *pslog = NULL;
4198 ID3DXBuffer *psbuffer = NULL;
4199 ID3DXConstantTable *psconstanttable = NULL;
4202 char temp[MAX_INPUTLINE];
4203 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4204 qboolean debugshader = gl_paranoid.integer != 0;
4205 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4206 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4209 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4210 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4212 if ((!vsbin && vertstring) || (!psbin && fragstring))
4214 const char* dllnames_d3dx9 [] =
4238 dllhandle_t d3dx9_dll = NULL;
4239 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4240 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4241 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4242 dllfunction_t d3dx9_dllfuncs[] =
4244 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
4245 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
4246 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
4249 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4251 DWORD shaderflags = 0;
4253 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4254 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4255 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4256 if (vertstring && vertstring[0])
4260 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4261 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4262 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4263 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4266 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4269 vsbinsize = vsbuffer->GetBufferSize();
4270 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4271 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4272 vsbuffer->Release();
4276 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4277 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4281 if (fragstring && fragstring[0])
4285 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4286 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4287 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4288 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4291 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4294 psbinsize = psbuffer->GetBufferSize();
4295 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4296 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4297 psbuffer->Release();
4301 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4302 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4306 Sys_UnloadLibrary(&d3dx9_dll);
4309 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4313 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4314 if (FAILED(vsresult))
4315 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4316 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4317 if (FAILED(psresult))
4318 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4320 // free the shader data
4321 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4322 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4325 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4328 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4329 int vertstring_length = 0;
4330 int geomstring_length = 0;
4331 int fragstring_length = 0;
4333 char *vertexstring, *geometrystring, *fragmentstring;
4334 char *vertstring, *geomstring, *fragstring;
4335 char permutationname[256];
4336 char cachename[256];
4337 int vertstrings_count = 0;
4338 int geomstrings_count = 0;
4339 int fragstrings_count = 0;
4340 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4341 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4342 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4347 p->vertexshader = NULL;
4348 p->pixelshader = NULL;
4350 permutationname[0] = 0;
4352 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
4353 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4354 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4356 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4357 strlcat(cachename, "hlsl/", sizeof(cachename));
4359 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4360 vertstrings_count = 0;
4361 geomstrings_count = 0;
4362 fragstrings_count = 0;
4363 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4364 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4365 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4367 // the first pretext is which type of shader to compile as
4368 // (later these will all be bound together as a program object)
4369 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4370 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4371 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4373 // the second pretext is the mode (for example a light source)
4374 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4375 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4376 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4377 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4378 strlcat(cachename, modeinfo->name, sizeof(cachename));
4380 // now add all the permutation pretexts
4381 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4383 if (permutation & (1<<i))
4385 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4386 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4387 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4388 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4389 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4393 // keep line numbers correct
4394 vertstrings_list[vertstrings_count++] = "\n";
4395 geomstrings_list[geomstrings_count++] = "\n";
4396 fragstrings_list[fragstrings_count++] = "\n";
4401 R_CompileShader_AddStaticParms(mode, permutation);
4402 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4403 vertstrings_count += shaderstaticparms_count;
4404 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4405 geomstrings_count += shaderstaticparms_count;
4406 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4407 fragstrings_count += shaderstaticparms_count;
4409 // replace spaces in the cachename with _ characters
4410 for (i = 0;cachename[i];i++)
4411 if (cachename[i] == ' ')
4414 // now append the shader text itself
4415 vertstrings_list[vertstrings_count++] = vertexstring;
4416 geomstrings_list[geomstrings_count++] = geometrystring;
4417 fragstrings_list[fragstrings_count++] = fragmentstring;
4419 // if any sources were NULL, clear the respective list
4421 vertstrings_count = 0;
4422 if (!geometrystring)
4423 geomstrings_count = 0;
4424 if (!fragmentstring)
4425 fragstrings_count = 0;
4427 vertstring_length = 0;
4428 for (i = 0;i < vertstrings_count;i++)
4429 vertstring_length += strlen(vertstrings_list[i]);
4430 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4431 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4432 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4434 geomstring_length = 0;
4435 for (i = 0;i < geomstrings_count;i++)
4436 geomstring_length += strlen(geomstrings_list[i]);
4437 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4438 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4439 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4441 fragstring_length = 0;
4442 for (i = 0;i < fragstrings_count;i++)
4443 fragstring_length += strlen(fragstrings_list[i]);
4444 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4445 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4446 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4448 // try to load the cached shader, or generate one
4449 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4451 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4452 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4454 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
4458 Mem_Free(vertstring);
4460 Mem_Free(geomstring);
4462 Mem_Free(fragstring);
4464 Mem_Free(vertexstring);
4466 Mem_Free(geometrystring);
4468 Mem_Free(fragmentstring);
4471 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4472 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4473 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);}
4474 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);}
4475 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);}
4476 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);}
4478 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4479 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4480 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);}
4481 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);}
4482 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);}
4483 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);}
4485 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4487 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4488 if (r_hlsl_permutation != perm)
4490 r_hlsl_permutation = perm;
4491 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4493 if (!r_hlsl_permutation->compiled)
4494 R_HLSL_CompilePermutation(perm, mode, permutation);
4495 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4497 // remove features until we find a valid permutation
4499 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4501 // reduce i more quickly whenever it would not remove any bits
4502 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4503 if (!(permutation & j))
4506 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4507 if (!r_hlsl_permutation->compiled)
4508 R_HLSL_CompilePermutation(perm, mode, permutation);
4509 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4512 if (i >= SHADERPERMUTATION_COUNT)
4514 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4515 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4516 return; // no bit left to clear, entire mode is broken
4520 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4521 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4523 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4524 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4525 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4529 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
4531 DPSOFTRAST_SetShader(mode, permutation);
4532 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
4533 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
4534 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
4537 void R_GLSL_Restart_f(void)
4539 unsigned int i, limit;
4540 if (glslshaderstring && glslshaderstring != builtinshaderstring)
4541 Mem_Free(glslshaderstring);
4542 glslshaderstring = NULL;
4543 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
4544 Mem_Free(hlslshaderstring);
4545 hlslshaderstring = NULL;
4546 switch(vid.renderpath)
4548 case RENDERPATH_D3D9:
4551 r_hlsl_permutation_t *p;
4552 r_hlsl_permutation = NULL;
4553 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
4554 for (i = 0;i < limit;i++)
4556 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
4558 if (p->vertexshader)
4559 IDirect3DVertexShader9_Release(p->vertexshader);
4561 IDirect3DPixelShader9_Release(p->pixelshader);
4562 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
4565 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4569 case RENDERPATH_D3D10:
4570 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4572 case RENDERPATH_D3D11:
4573 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4575 case RENDERPATH_GL20:
4576 case RENDERPATH_GLES2:
4578 r_glsl_permutation_t *p;
4579 r_glsl_permutation = NULL;
4580 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4581 for (i = 0;i < limit;i++)
4583 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4585 GL_Backend_FreeProgram(p->program);
4586 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4589 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4592 case RENDERPATH_GL13:
4593 case RENDERPATH_GL11:
4595 case RENDERPATH_SOFT:
4600 void R_GLSL_DumpShader_f(void)
4605 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4608 FS_Print(file, "/* The engine may define the following macros:\n");
4609 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4610 for (i = 0;i < SHADERMODE_COUNT;i++)
4611 FS_Print(file, glslshadermodeinfo[i].pretext);
4612 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4613 FS_Print(file, shaderpermutationinfo[i].pretext);
4614 FS_Print(file, "*/\n");
4615 FS_Print(file, builtinshaderstring);
4617 Con_Printf("glsl/default.glsl written\n");
4620 Con_Printf("failed to write to glsl/default.glsl\n");
4622 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
4625 FS_Print(file, "/* The engine may define the following macros:\n");
4626 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4627 for (i = 0;i < SHADERMODE_COUNT;i++)
4628 FS_Print(file, hlslshadermodeinfo[i].pretext);
4629 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4630 FS_Print(file, shaderpermutationinfo[i].pretext);
4631 FS_Print(file, "*/\n");
4632 FS_Print(file, builtinhlslshaderstring);
4634 Con_Printf("hlsl/default.hlsl written\n");
4637 Con_Printf("failed to write to hlsl/default.hlsl\n");
4640 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4643 texturemode = GL_MODULATE;
4644 switch (vid.renderpath)
4646 case RENDERPATH_D3D9:
4648 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))));
4649 R_Mesh_TexBind(GL20TU_FIRST , first );
4650 R_Mesh_TexBind(GL20TU_SECOND, second);
4653 case RENDERPATH_D3D10:
4654 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4656 case RENDERPATH_D3D11:
4657 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4659 case RENDERPATH_GL20:
4660 case RENDERPATH_GLES2:
4661 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))));
4662 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
4663 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
4665 case RENDERPATH_GL13:
4666 R_Mesh_TexBind(0, first );
4667 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4668 R_Mesh_TexBind(1, second);
4670 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4672 case RENDERPATH_GL11:
4673 R_Mesh_TexBind(0, first );
4675 case RENDERPATH_SOFT:
4676 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))));
4677 R_Mesh_TexBind(GL20TU_FIRST , first );
4678 R_Mesh_TexBind(GL20TU_SECOND, second);
4683 void R_SetupShader_DepthOrShadow(void)
4685 switch (vid.renderpath)
4687 case RENDERPATH_D3D9:
4689 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4692 case RENDERPATH_D3D10:
4693 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4695 case RENDERPATH_D3D11:
4696 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4698 case RENDERPATH_GL20:
4699 case RENDERPATH_GLES2:
4700 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4702 case RENDERPATH_GL13:
4703 R_Mesh_TexBind(0, 0);
4704 R_Mesh_TexBind(1, 0);
4706 case RENDERPATH_GL11:
4707 R_Mesh_TexBind(0, 0);
4709 case RENDERPATH_SOFT:
4710 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
4715 void R_SetupShader_ShowDepth(void)
4717 switch (vid.renderpath)
4719 case RENDERPATH_D3D9:
4721 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
4724 case RENDERPATH_D3D10:
4725 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4727 case RENDERPATH_D3D11:
4728 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4730 case RENDERPATH_GL20:
4731 case RENDERPATH_GLES2:
4732 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4734 case RENDERPATH_GL13:
4736 case RENDERPATH_GL11:
4738 case RENDERPATH_SOFT:
4739 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
4744 extern qboolean r_shadow_usingdeferredprepass;
4745 extern cvar_t r_shadow_deferred_8bitrange;
4746 extern rtexture_t *r_shadow_attenuationgradienttexture;
4747 extern rtexture_t *r_shadow_attenuation2dtexture;
4748 extern rtexture_t *r_shadow_attenuation3dtexture;
4749 extern qboolean r_shadow_usingshadowmap2d;
4750 extern qboolean r_shadow_usingshadowmaportho;
4751 extern float r_shadow_shadowmap_texturescale[2];
4752 extern float r_shadow_shadowmap_parameters[4];
4753 extern qboolean r_shadow_shadowmapvsdct;
4754 extern qboolean r_shadow_shadowmapsampler;
4755 extern int r_shadow_shadowmappcf;
4756 extern rtexture_t *r_shadow_shadowmap2dtexture;
4757 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
4758 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4759 extern matrix4x4_t r_shadow_shadowmapmatrix;
4760 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4761 extern int r_shadow_prepass_width;
4762 extern int r_shadow_prepass_height;
4763 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4764 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4765 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
4766 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4767 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4768 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
4770 // a blendfunc allows colormod if:
4771 // a) it can never keep the destination pixel invariant, or
4772 // b) it can keep the destination pixel invariant, and still can do so if colormodded
4773 // this is to prevent unintended side effects from colormod
4776 // IF there is a (s, sa) for which for all (d, da),
4777 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
4778 // THEN, for this (s, sa) and all (colormod, d, da):
4779 // s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
4780 // OBVIOUSLY, this means that
4781 // s*colormod * src(s*colormod, d, sa, da) = 0
4782 // dst(s*colormod, d, sa, da) = 1
4784 // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
4786 // main condition to leave dst color invariant:
4787 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
4789 // s * 0 + d * dst(s, d, sa, da) == d
4790 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4791 // => colormod is a problem for GL_SRC_COLOR only
4793 // s + d * dst(s, d, sa, da) == d
4795 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4796 // => colormod is never problematic for these
4797 // src == GL_SRC_COLOR:
4798 // s*s + d * dst(s, d, sa, da) == d
4800 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4801 // => colormod is never problematic for these
4802 // src == GL_ONE_MINUS_SRC_COLOR:
4803 // s*(1-s) + d * dst(s, d, sa, da) == d
4804 // => s == 0 or s == 1
4805 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4806 // => colormod is a problem for GL_SRC_COLOR only
4807 // src == GL_DST_COLOR
4808 // s*d + d * dst(s, d, sa, da) == d
4810 // => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4811 // => colormod is always a problem
4814 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4815 // => colormod is never problematic for these
4816 // => BUT, we do not know s! We must assume it is problematic
4817 // then... except in GL_ONE case, where we know all invariant
4819 // src == GL_ONE_MINUS_DST_COLOR
4820 // s*(1-d) + d * dst(s, d, sa, da) == d
4821 // => s == 0 (1-d is impossible to handle for our desired result)
4822 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4823 // => colormod is never problematic for these
4824 // src == GL_SRC_ALPHA
4825 // s*sa + d * dst(s, d, sa, da) == d
4826 // => s == 0, or sa == 0
4827 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4828 // => colormod breaks in the case GL_SRC_COLOR only
4829 // src == GL_ONE_MINUS_SRC_ALPHA
4830 // s*(1-sa) + d * dst(s, d, sa, da) == d
4831 // => s == 0, or sa == 1
4832 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4833 // => colormod breaks in the case GL_SRC_COLOR only
4834 // src == GL_DST_ALPHA
4835 // s*da + d * dst(s, d, sa, da) == d
4837 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4838 // => colormod is never problematic for these
4843 case GL_ONE_MINUS_SRC_COLOR:
4845 case GL_ONE_MINUS_SRC_ALPHA:
4846 if(dst == GL_SRC_COLOR)
4851 case GL_ONE_MINUS_DST_COLOR:
4853 case GL_ONE_MINUS_DST_ALPHA:
4863 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)
4865 // select a permutation of the lighting shader appropriate to this
4866 // combination of texture, entity, light source, and fogging, only use the
4867 // minimum features necessary to avoid wasting rendering time in the
4868 // fragment shader on features that are not being used
4869 unsigned int permutation = 0;
4870 unsigned int mode = 0;
4871 qboolean allow_colormod;
4872 static float dummy_colormod[3] = {1, 1, 1};
4873 float *colormod = rsurface.colormod;
4875 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
4876 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4877 permutation |= SHADERPERMUTATION_ALPHAKILL;
4878 if (rsurfacepass == RSURFPASS_BACKGROUND)
4880 // distorted background
4881 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4883 mode = SHADERMODE_WATER;
4884 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
4885 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
4886 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
4888 // this is the right thing to do for wateralpha
4889 GL_BlendFunc(GL_ONE, GL_ZERO);
4890 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4894 // this is the right thing to do for entity alpha
4895 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4896 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4899 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
4901 mode = SHADERMODE_REFRACTION;
4902 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4903 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4907 mode = SHADERMODE_GENERIC;
4908 permutation |= SHADERPERMUTATION_DIFFUSE;
4909 GL_BlendFunc(GL_ONE, GL_ZERO);
4910 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4913 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4915 if (r_glsl_offsetmapping.integer)
4917 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4918 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4919 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4920 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4921 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4923 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4924 if (r_glsl_offsetmapping_reliefmapping.integer)
4925 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4928 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4929 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4930 // normalmap (deferred prepass), may use alpha test on diffuse
4931 mode = SHADERMODE_DEFERREDGEOMETRY;
4932 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4933 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4934 GL_BlendFunc(GL_ONE, GL_ZERO);
4935 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4937 else if (rsurfacepass == RSURFPASS_RTLIGHT)
4939 if (r_glsl_offsetmapping.integer)
4941 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4942 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4943 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4944 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4945 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4947 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4948 if (r_glsl_offsetmapping_reliefmapping.integer)
4949 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4952 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4953 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4955 mode = SHADERMODE_LIGHTSOURCE;
4956 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4957 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4958 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4959 permutation |= SHADERPERMUTATION_CUBEFILTER;
4960 if (diffusescale > 0)
4961 permutation |= SHADERPERMUTATION_DIFFUSE;
4962 if (specularscale > 0)
4963 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4964 if (r_refdef.fogenabled)
4965 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4966 if (rsurface.texture->colormapping)
4967 permutation |= SHADERPERMUTATION_COLORMAPPING;
4968 if (r_shadow_usingshadowmap2d)
4970 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4971 if(r_shadow_shadowmapvsdct)
4972 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4974 if (r_shadow_shadowmapsampler)
4975 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4976 if (r_shadow_shadowmappcf > 1)
4977 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4978 else if (r_shadow_shadowmappcf)
4979 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4981 if (rsurface.texture->reflectmasktexture)
4982 permutation |= SHADERPERMUTATION_REFLECTCUBE;
4983 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4984 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
4986 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4988 if (r_glsl_offsetmapping.integer)
4990 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4991 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4992 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4993 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4994 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4996 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4997 if (r_glsl_offsetmapping_reliefmapping.integer)
4998 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5001 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5002 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5003 // unshaded geometry (fullbright or ambient model lighting)
5004 mode = SHADERMODE_FLATCOLOR;
5005 ambientscale = diffusescale = specularscale = 0;
5006 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5007 permutation |= SHADERPERMUTATION_GLOW;
5008 if (r_refdef.fogenabled)
5009 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5010 if (rsurface.texture->colormapping)
5011 permutation |= SHADERPERMUTATION_COLORMAPPING;
5012 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5014 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5015 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5017 if (r_shadow_shadowmapsampler)
5018 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5019 if (r_shadow_shadowmappcf > 1)
5020 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5021 else if (r_shadow_shadowmappcf)
5022 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5024 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5025 permutation |= SHADERPERMUTATION_REFLECTION;
5026 if (rsurface.texture->reflectmasktexture)
5027 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5028 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5029 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5031 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5033 if (r_glsl_offsetmapping.integer)
5035 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5036 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5037 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5038 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5039 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5041 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5042 if (r_glsl_offsetmapping_reliefmapping.integer)
5043 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5046 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5047 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5048 // directional model lighting
5049 mode = SHADERMODE_LIGHTDIRECTION;
5050 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5051 permutation |= SHADERPERMUTATION_GLOW;
5052 permutation |= SHADERPERMUTATION_DIFFUSE;
5053 if (specularscale > 0)
5054 permutation |= SHADERPERMUTATION_SPECULAR;
5055 if (r_refdef.fogenabled)
5056 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5057 if (rsurface.texture->colormapping)
5058 permutation |= SHADERPERMUTATION_COLORMAPPING;
5059 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5061 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5062 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5064 if (r_shadow_shadowmapsampler)
5065 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5066 if (r_shadow_shadowmappcf > 1)
5067 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5068 else if (r_shadow_shadowmappcf)
5069 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5071 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5072 permutation |= SHADERPERMUTATION_REFLECTION;
5073 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5074 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5075 if (rsurface.texture->reflectmasktexture)
5076 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5077 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5078 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5080 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5082 if (r_glsl_offsetmapping.integer)
5084 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5085 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5086 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5087 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5088 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5090 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5091 if (r_glsl_offsetmapping_reliefmapping.integer)
5092 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5095 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5096 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5097 // ambient model lighting
5098 mode = SHADERMODE_LIGHTDIRECTION;
5099 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5100 permutation |= SHADERPERMUTATION_GLOW;
5101 if (r_refdef.fogenabled)
5102 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5103 if (rsurface.texture->colormapping)
5104 permutation |= SHADERPERMUTATION_COLORMAPPING;
5105 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5107 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5108 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5110 if (r_shadow_shadowmapsampler)
5111 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5112 if (r_shadow_shadowmappcf > 1)
5113 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5114 else if (r_shadow_shadowmappcf)
5115 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5117 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5118 permutation |= SHADERPERMUTATION_REFLECTION;
5119 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5120 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5121 if (rsurface.texture->reflectmasktexture)
5122 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5123 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5124 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5128 if (r_glsl_offsetmapping.integer)
5130 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5131 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5132 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5133 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5134 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5136 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5137 if (r_glsl_offsetmapping_reliefmapping.integer)
5138 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5141 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5142 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5144 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5145 permutation |= SHADERPERMUTATION_GLOW;
5146 if (r_refdef.fogenabled)
5147 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5148 if (rsurface.texture->colormapping)
5149 permutation |= SHADERPERMUTATION_COLORMAPPING;
5150 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5152 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5153 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5155 if (r_shadow_shadowmapsampler)
5156 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5157 if (r_shadow_shadowmappcf > 1)
5158 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5159 else if (r_shadow_shadowmappcf)
5160 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5162 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5163 permutation |= SHADERPERMUTATION_REFLECTION;
5164 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5165 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5166 if (rsurface.texture->reflectmasktexture)
5167 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5168 if (FAKELIGHT_ENABLED)
5170 // fake lightmapping (q1bsp, q3bsp, fullbright map)
5171 mode = SHADERMODE_FAKELIGHT;
5172 permutation |= SHADERPERMUTATION_DIFFUSE;
5173 if (specularscale > 0)
5174 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5176 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5178 // deluxemapping (light direction texture)
5179 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5180 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5182 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5183 permutation |= SHADERPERMUTATION_DIFFUSE;
5184 if (specularscale > 0)
5185 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5187 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5189 // fake deluxemapping (uniform light direction in tangentspace)
5190 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5191 permutation |= SHADERPERMUTATION_DIFFUSE;
5192 if (specularscale > 0)
5193 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5195 else if (rsurface.uselightmaptexture)
5197 // ordinary lightmapping (q1bsp, q3bsp)
5198 mode = SHADERMODE_LIGHTMAP;
5202 // ordinary vertex coloring (q3bsp)
5203 mode = SHADERMODE_VERTEXCOLOR;
5205 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5206 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5209 colormod = dummy_colormod;
5210 switch(vid.renderpath)
5212 case RENDERPATH_D3D9:
5214 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);
5215 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5216 R_SetupShader_SetPermutationHLSL(mode, permutation);
5217 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5218 if (mode == SHADERMODE_LIGHTSOURCE)
5220 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5221 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5225 if (mode == SHADERMODE_LIGHTDIRECTION)
5227 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5230 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5231 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5232 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5233 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5234 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5236 if (mode == SHADERMODE_LIGHTSOURCE)
5238 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5239 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5240 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5241 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5242 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5244 // additive passes are only darkened by fog, not tinted
5245 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5246 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5250 if (mode == SHADERMODE_FLATCOLOR)
5252 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5254 else if (mode == SHADERMODE_LIGHTDIRECTION)
5256 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]);
5257 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5258 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);
5259 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);
5260 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5261 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5262 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5266 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5267 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5268 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);
5269 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);
5270 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5272 // additive passes are only darkened by fog, not tinted
5273 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5274 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5276 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5277 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);
5278 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5279 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5280 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5281 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5282 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5283 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5284 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5285 if (mode == SHADERMODE_WATER)
5286 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5288 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5289 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5290 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5291 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));
5292 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5293 if (rsurface.texture->pantstexture)
5294 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5296 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5297 if (rsurface.texture->shirttexture)
5298 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5300 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5301 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5302 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5303 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5304 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5305 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5306 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5307 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5309 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5310 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5311 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5312 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5313 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5314 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5315 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5316 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5317 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5318 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5319 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5320 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5321 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5322 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5323 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5324 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5325 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5326 if (rsurfacepass == RSURFPASS_BACKGROUND)
5328 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5329 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5330 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5334 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5336 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5337 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5338 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5339 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5340 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5342 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5343 if (rsurface.rtlight)
5345 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5346 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5351 case RENDERPATH_D3D10:
5352 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5354 case RENDERPATH_D3D11:
5355 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5357 case RENDERPATH_GL20:
5358 case RENDERPATH_GLES2:
5359 if (!vid.useinterleavedarrays)
5361 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);
5362 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5363 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5364 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5365 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5366 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5367 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5368 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5372 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);
5373 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5375 R_SetupShader_SetPermutationGLSL(mode, permutation);
5376 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5377 if (mode == SHADERMODE_LIGHTSOURCE)
5379 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5380 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5381 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5382 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5383 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5384 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);
5386 // additive passes are only darkened by fog, not tinted
5387 if (r_glsl_permutation->loc_FogColor >= 0)
5388 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5389 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5393 if (mode == SHADERMODE_FLATCOLOR)
5395 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5397 else if (mode == SHADERMODE_LIGHTDIRECTION)
5399 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]);
5400 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]);
5401 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);
5402 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);
5403 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);
5404 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]);
5405 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]);
5409 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]);
5410 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]);
5411 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);
5412 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);
5413 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);
5415 // additive passes are only darkened by fog, not tinted
5416 if (r_glsl_permutation->loc_FogColor >= 0)
5418 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5419 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5421 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5423 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);
5424 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]);
5425 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]);
5426 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]);
5427 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]);
5428 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5429 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5430 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5431 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]);
5433 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5434 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5435 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5436 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]);
5437 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]);
5439 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5440 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));
5441 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5442 if (r_glsl_permutation->loc_Color_Pants >= 0)
5444 if (rsurface.texture->pantstexture)
5445 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5447 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5449 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5451 if (rsurface.texture->shirttexture)
5452 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5454 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5456 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]);
5457 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5458 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5459 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5460 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5461 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]);
5462 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5464 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
5465 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
5466 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
5467 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
5468 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
5469 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
5470 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
5471 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
5472 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
5473 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
5474 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
5475 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
5476 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
5477 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
5478 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);
5479 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
5480 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
5481 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5482 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5483 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
5484 if (rsurfacepass == RSURFPASS_BACKGROUND)
5486 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);
5487 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);
5488 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);
5492 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);
5494 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
5495 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
5496 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
5497 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
5498 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5500 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
5501 if (rsurface.rtlight)
5503 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
5504 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
5509 case RENDERPATH_GL13:
5510 case RENDERPATH_GL11:
5512 case RENDERPATH_SOFT:
5513 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);
5514 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
5515 R_SetupShader_SetPermutationSoft(mode, permutation);
5516 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
5517 if (mode == SHADERMODE_LIGHTSOURCE)
5519 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
5520 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5521 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5522 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5523 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5524 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5526 // additive passes are only darkened by fog, not tinted
5527 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
5528 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5532 if (mode == SHADERMODE_FLATCOLOR)
5534 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5536 else if (mode == SHADERMODE_LIGHTDIRECTION)
5538 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]);
5539 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5540 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);
5541 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);
5542 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5543 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]);
5544 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5548 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5549 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5550 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);
5551 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);
5552 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5554 // additive passes are only darkened by fog, not tinted
5555 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5556 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
5558 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5559 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);
5560 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5561 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5562 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]);
5563 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]);
5564 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5565 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
5566 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5567 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5569 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
5570 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
5571 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
5572 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5573 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]);
5575 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5576 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));
5577 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5578 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
5580 if (rsurface.texture->pantstexture)
5581 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5583 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
5585 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
5587 if (rsurface.texture->shirttexture)
5588 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5590 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
5592 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5593 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
5594 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
5595 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
5596 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5597 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5598 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5600 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5601 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5602 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5603 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5604 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5605 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5606 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5607 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5608 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5609 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5610 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5611 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5612 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5613 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5614 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5615 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5616 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5617 if (rsurfacepass == RSURFPASS_BACKGROUND)
5619 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5620 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5621 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5625 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5627 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5628 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5629 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5630 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5631 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5633 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5634 if (rsurface.rtlight)
5636 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5637 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5644 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5646 // select a permutation of the lighting shader appropriate to this
5647 // combination of texture, entity, light source, and fogging, only use the
5648 // minimum features necessary to avoid wasting rendering time in the
5649 // fragment shader on features that are not being used
5650 unsigned int permutation = 0;
5651 unsigned int mode = 0;
5652 const float *lightcolorbase = rtlight->currentcolor;
5653 float ambientscale = rtlight->ambientscale;
5654 float diffusescale = rtlight->diffusescale;
5655 float specularscale = rtlight->specularscale;
5656 // this is the location of the light in view space
5657 vec3_t viewlightorigin;
5658 // this transforms from view space (camera) to light space (cubemap)
5659 matrix4x4_t viewtolight;
5660 matrix4x4_t lighttoview;
5661 float viewtolight16f[16];
5662 float range = 1.0f / r_shadow_deferred_8bitrange.value;
5664 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
5665 if (rtlight->currentcubemap != r_texture_whitecube)
5666 permutation |= SHADERPERMUTATION_CUBEFILTER;
5667 if (diffusescale > 0)
5668 permutation |= SHADERPERMUTATION_DIFFUSE;
5669 if (specularscale > 0)
5670 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5671 if (r_shadow_usingshadowmap2d)
5673 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5674 if (r_shadow_shadowmapvsdct)
5675 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5677 if (r_shadow_shadowmapsampler)
5678 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5679 if (r_shadow_shadowmappcf > 1)
5680 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5681 else if (r_shadow_shadowmappcf)
5682 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5684 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
5685 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
5686 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
5687 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
5688 switch(vid.renderpath)
5690 case RENDERPATH_D3D9:
5692 R_SetupShader_SetPermutationHLSL(mode, permutation);
5693 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5694 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
5695 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
5696 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
5697 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
5698 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5699 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5700 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5701 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5702 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5704 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5705 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
5706 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5707 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5708 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
5709 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5712 case RENDERPATH_D3D10:
5713 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5715 case RENDERPATH_D3D11:
5716 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5718 case RENDERPATH_GL20:
5719 case RENDERPATH_GLES2:
5720 R_SetupShader_SetPermutationGLSL(mode, permutation);
5721 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5722 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
5723 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);
5724 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);
5725 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);
5726 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]);
5727 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]);
5728 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));
5729 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]);
5730 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
5732 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
5733 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
5734 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
5735 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
5736 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
5737 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
5739 case RENDERPATH_GL13:
5740 case RENDERPATH_GL11:
5742 case RENDERPATH_SOFT:
5743 R_SetupShader_SetPermutationGLSL(mode, permutation);
5744 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5745 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
5746 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
5747 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
5748 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
5749 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5750 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]);
5751 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));
5752 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5753 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5755 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5756 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5757 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5758 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5759 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
5760 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5765 void R_SetupShader_DeferredBounceLight(void)
5767 // array of particle lights that contribute only ambient color
5768 unsigned int permutation = 0;
5769 unsigned int mode = 0;
5770 mode = SHADERMODE_DEFERREDBOUNCELIGHT;
5771 switch(vid.renderpath)
5773 case RENDERPATH_D3D9:
5775 R_SetupShader_SetPermutationHLSL(mode, permutation);
5776 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5777 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5779 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
5782 case RENDERPATH_D3D10:
5783 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5785 case RENDERPATH_D3D11:
5786 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5788 case RENDERPATH_GL20:
5789 case RENDERPATH_GLES2:
5790 R_SetupShader_SetPermutationGLSL(mode, permutation);
5791 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]);
5792 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
5794 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
5796 case RENDERPATH_GL13:
5797 case RENDERPATH_GL11:
5799 case RENDERPATH_SOFT:
5800 R_SetupShader_SetPermutationGLSL(mode, permutation);
5801 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5802 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5804 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5809 #define SKINFRAME_HASH 1024
5813 int loadsequence; // incremented each level change
5814 memexpandablearray_t array;
5815 skinframe_t *hash[SKINFRAME_HASH];
5818 r_skinframe_t r_skinframe;
5820 void R_SkinFrame_PrepareForPurge(void)
5822 r_skinframe.loadsequence++;
5823 // wrap it without hitting zero
5824 if (r_skinframe.loadsequence >= 200)
5825 r_skinframe.loadsequence = 1;
5828 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5832 // mark the skinframe as used for the purging code
5833 skinframe->loadsequence = r_skinframe.loadsequence;
5836 void R_SkinFrame_Purge(void)
5840 for (i = 0;i < SKINFRAME_HASH;i++)
5842 for (s = r_skinframe.hash[i];s;s = s->next)
5844 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5846 if (s->merged == s->base)
5848 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5849 R_PurgeTexture(s->stain );s->stain = NULL;
5850 R_PurgeTexture(s->merged);s->merged = NULL;
5851 R_PurgeTexture(s->base );s->base = NULL;
5852 R_PurgeTexture(s->pants );s->pants = NULL;
5853 R_PurgeTexture(s->shirt );s->shirt = NULL;
5854 R_PurgeTexture(s->nmap );s->nmap = NULL;
5855 R_PurgeTexture(s->gloss );s->gloss = NULL;
5856 R_PurgeTexture(s->glow );s->glow = NULL;
5857 R_PurgeTexture(s->fog );s->fog = NULL;
5858 R_PurgeTexture(s->reflect);s->reflect = NULL;
5859 s->loadsequence = 0;
5865 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5867 char basename[MAX_QPATH];
5869 Image_StripImageExtension(name, basename, sizeof(basename));
5871 if( last == NULL ) {
5873 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5874 item = r_skinframe.hash[hashindex];
5879 // linearly search through the hash bucket
5880 for( ; item ; item = item->next ) {
5881 if( !strcmp( item->basename, basename ) ) {
5888 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5892 char basename[MAX_QPATH];
5894 Image_StripImageExtension(name, basename, sizeof(basename));
5896 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5897 for (item = r_skinframe.hash[hashindex];item;item = item->next)
5898 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5902 rtexture_t *dyntexture;
5903 // check whether its a dynamic texture
5904 dyntexture = CL_GetDynTexture( basename );
5905 if (!add && !dyntexture)
5907 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5908 memset(item, 0, sizeof(*item));
5909 strlcpy(item->basename, basename, sizeof(item->basename));
5910 item->base = dyntexture; // either NULL or dyntexture handle
5911 item->textureflags = textureflags;
5912 item->comparewidth = comparewidth;
5913 item->compareheight = compareheight;
5914 item->comparecrc = comparecrc;
5915 item->next = r_skinframe.hash[hashindex];
5916 r_skinframe.hash[hashindex] = item;
5918 else if( item->base == NULL )
5920 rtexture_t *dyntexture;
5921 // check whether its a dynamic texture
5922 // 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]
5923 dyntexture = CL_GetDynTexture( basename );
5924 item->base = dyntexture; // either NULL or dyntexture handle
5927 R_SkinFrame_MarkUsed(item);
5931 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5933 unsigned long long avgcolor[5], wsum; \
5941 for(pix = 0; pix < cnt; ++pix) \
5944 for(comp = 0; comp < 3; ++comp) \
5946 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5949 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5951 for(comp = 0; comp < 3; ++comp) \
5952 avgcolor[comp] += getpixel * w; \
5955 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5956 avgcolor[4] += getpixel; \
5958 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5960 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5961 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5962 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5963 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5966 extern cvar_t gl_picmip;
5967 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5970 unsigned char *pixels;
5971 unsigned char *bumppixels;
5972 unsigned char *basepixels = NULL;
5973 int basepixels_width = 0;
5974 int basepixels_height = 0;
5975 skinframe_t *skinframe;
5976 rtexture_t *ddsbase = NULL;
5977 qboolean ddshasalpha = false;
5978 float ddsavgcolor[4];
5979 char basename[MAX_QPATH];
5980 int miplevel = R_PicmipForFlags(textureflags);
5981 int savemiplevel = miplevel;
5984 if (cls.state == ca_dedicated)
5987 // return an existing skinframe if already loaded
5988 // if loading of the first image fails, don't make a new skinframe as it
5989 // would cause all future lookups of this to be missing
5990 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5991 if (skinframe && skinframe->base)
5994 Image_StripImageExtension(name, basename, sizeof(basename));
5996 // check for DDS texture file first
5997 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
5999 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6000 if (basepixels == NULL)
6004 // FIXME handle miplevel
6006 if (developer_loading.integer)
6007 Con_Printf("loading skin \"%s\"\n", name);
6009 // we've got some pixels to store, so really allocate this new texture now
6011 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6012 skinframe->stain = NULL;
6013 skinframe->merged = NULL;
6014 skinframe->base = NULL;
6015 skinframe->pants = NULL;
6016 skinframe->shirt = NULL;
6017 skinframe->nmap = NULL;
6018 skinframe->gloss = NULL;
6019 skinframe->glow = NULL;
6020 skinframe->fog = NULL;
6021 skinframe->reflect = NULL;
6022 skinframe->hasalpha = false;
6026 skinframe->base = ddsbase;
6027 skinframe->hasalpha = ddshasalpha;
6028 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6029 if (r_loadfog && skinframe->hasalpha)
6030 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6031 //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]);
6035 basepixels_width = image_width;
6036 basepixels_height = image_height;
6037 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);
6038 if (textureflags & TEXF_ALPHA)
6040 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6042 if (basepixels[j] < 255)
6044 skinframe->hasalpha = true;
6048 if (r_loadfog && skinframe->hasalpha)
6050 // has transparent pixels
6051 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6052 for (j = 0;j < image_width * image_height * 4;j += 4)
6057 pixels[j+3] = basepixels[j+3];
6059 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);
6063 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6064 //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]);
6065 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6066 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6067 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6068 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6073 mymiplevel = savemiplevel;
6074 if (r_loadnormalmap)
6075 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);
6076 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6078 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6079 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6080 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6081 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6084 // _norm is the name used by tenebrae and has been adopted as standard
6085 if (r_loadnormalmap && skinframe->nmap == NULL)
6087 mymiplevel = savemiplevel;
6088 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6090 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);
6094 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6096 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6097 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6098 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);
6100 Mem_Free(bumppixels);
6102 else if (r_shadow_bumpscale_basetexture.value > 0)
6104 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6105 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6106 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);
6109 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6110 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6113 // _luma is supported only for tenebrae compatibility
6114 // _glow is the preferred name
6115 mymiplevel = savemiplevel;
6116 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))))
6118 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);
6119 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6120 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6121 Mem_Free(pixels);pixels = NULL;
6124 mymiplevel = savemiplevel;
6125 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6127 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);
6128 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6129 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6134 mymiplevel = savemiplevel;
6135 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6137 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);
6138 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6139 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6144 mymiplevel = savemiplevel;
6145 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6147 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);
6148 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6149 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6154 mymiplevel = savemiplevel;
6155 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6157 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);
6158 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6159 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6165 Mem_Free(basepixels);
6170 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6171 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6174 unsigned char *temp1, *temp2;
6175 skinframe_t *skinframe;
6177 if (cls.state == ca_dedicated)
6180 // if already loaded just return it, otherwise make a new skinframe
6181 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6182 if (skinframe && skinframe->base)
6185 skinframe->stain = NULL;
6186 skinframe->merged = NULL;
6187 skinframe->base = NULL;
6188 skinframe->pants = NULL;
6189 skinframe->shirt = NULL;
6190 skinframe->nmap = NULL;
6191 skinframe->gloss = NULL;
6192 skinframe->glow = NULL;
6193 skinframe->fog = NULL;
6194 skinframe->reflect = NULL;
6195 skinframe->hasalpha = false;
6197 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6201 if (developer_loading.integer)
6202 Con_Printf("loading 32bit skin \"%s\"\n", name);
6204 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6206 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6207 temp2 = temp1 + width * height * 4;
6208 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6209 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);
6212 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6213 if (textureflags & TEXF_ALPHA)
6215 for (i = 3;i < width * height * 4;i += 4)
6217 if (skindata[i] < 255)
6219 skinframe->hasalpha = true;
6223 if (r_loadfog && skinframe->hasalpha)
6225 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6226 memcpy(fogpixels, skindata, width * height * 4);
6227 for (i = 0;i < width * height * 4;i += 4)
6228 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6229 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6230 Mem_Free(fogpixels);
6234 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6235 //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]);
6240 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6244 skinframe_t *skinframe;
6246 if (cls.state == ca_dedicated)
6249 // if already loaded just return it, otherwise make a new skinframe
6250 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6251 if (skinframe && skinframe->base)
6254 skinframe->stain = NULL;
6255 skinframe->merged = NULL;
6256 skinframe->base = NULL;
6257 skinframe->pants = NULL;
6258 skinframe->shirt = NULL;
6259 skinframe->nmap = NULL;
6260 skinframe->gloss = NULL;
6261 skinframe->glow = NULL;
6262 skinframe->fog = NULL;
6263 skinframe->reflect = NULL;
6264 skinframe->hasalpha = false;
6266 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6270 if (developer_loading.integer)
6271 Con_Printf("loading quake skin \"%s\"\n", name);
6273 // 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)
6274 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
6275 memcpy(skinframe->qpixels, skindata, width*height);
6276 skinframe->qwidth = width;
6277 skinframe->qheight = height;
6280 for (i = 0;i < width * height;i++)
6281 featuresmask |= palette_featureflags[skindata[i]];
6283 skinframe->hasalpha = false;
6284 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6285 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6286 skinframe->qgeneratemerged = true;
6287 skinframe->qgeneratebase = skinframe->qhascolormapping;
6288 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6290 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6291 //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]);
6296 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6300 unsigned char *skindata;
6302 if (!skinframe->qpixels)
6305 if (!skinframe->qhascolormapping)
6306 colormapped = false;
6310 if (!skinframe->qgeneratebase)
6315 if (!skinframe->qgeneratemerged)
6319 width = skinframe->qwidth;
6320 height = skinframe->qheight;
6321 skindata = skinframe->qpixels;
6323 if (skinframe->qgeneratenmap)
6325 unsigned char *temp1, *temp2;
6326 skinframe->qgeneratenmap = false;
6327 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6328 temp2 = temp1 + width * height * 4;
6329 // use either a custom palette or the quake palette
6330 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6331 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6332 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);
6336 if (skinframe->qgenerateglow)
6338 skinframe->qgenerateglow = false;
6339 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6344 skinframe->qgeneratebase = false;
6345 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);
6346 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6347 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6351 skinframe->qgeneratemerged = false;
6352 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);
6355 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6357 Mem_Free(skinframe->qpixels);
6358 skinframe->qpixels = NULL;
6362 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)
6365 skinframe_t *skinframe;
6367 if (cls.state == ca_dedicated)
6370 // if already loaded just return it, otherwise make a new skinframe
6371 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6372 if (skinframe && skinframe->base)
6375 skinframe->stain = NULL;
6376 skinframe->merged = NULL;
6377 skinframe->base = NULL;
6378 skinframe->pants = NULL;
6379 skinframe->shirt = NULL;
6380 skinframe->nmap = NULL;
6381 skinframe->gloss = NULL;
6382 skinframe->glow = NULL;
6383 skinframe->fog = NULL;
6384 skinframe->reflect = NULL;
6385 skinframe->hasalpha = false;
6387 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6391 if (developer_loading.integer)
6392 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6394 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6395 if (textureflags & TEXF_ALPHA)
6397 for (i = 0;i < width * height;i++)
6399 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6401 skinframe->hasalpha = true;
6405 if (r_loadfog && skinframe->hasalpha)
6406 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6409 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6410 //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]);
6415 skinframe_t *R_SkinFrame_LoadMissing(void)
6417 skinframe_t *skinframe;
6419 if (cls.state == ca_dedicated)
6422 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6423 skinframe->stain = NULL;
6424 skinframe->merged = NULL;
6425 skinframe->base = NULL;
6426 skinframe->pants = NULL;
6427 skinframe->shirt = NULL;
6428 skinframe->nmap = NULL;
6429 skinframe->gloss = NULL;
6430 skinframe->glow = NULL;
6431 skinframe->fog = NULL;
6432 skinframe->reflect = NULL;
6433 skinframe->hasalpha = false;
6435 skinframe->avgcolor[0] = rand() / RAND_MAX;
6436 skinframe->avgcolor[1] = rand() / RAND_MAX;
6437 skinframe->avgcolor[2] = rand() / RAND_MAX;
6438 skinframe->avgcolor[3] = 1;
6443 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6444 typedef struct suffixinfo_s
6447 qboolean flipx, flipy, flipdiagonal;
6450 static suffixinfo_t suffix[3][6] =
6453 {"px", false, false, false},
6454 {"nx", false, false, false},
6455 {"py", false, false, false},
6456 {"ny", false, false, false},
6457 {"pz", false, false, false},
6458 {"nz", false, false, false}
6461 {"posx", false, false, false},
6462 {"negx", false, false, false},
6463 {"posy", false, false, false},
6464 {"negy", false, false, false},
6465 {"posz", false, false, false},
6466 {"negz", false, false, false}
6469 {"rt", true, false, true},
6470 {"lf", false, true, true},
6471 {"ft", true, true, false},
6472 {"bk", false, false, false},
6473 {"up", true, false, true},
6474 {"dn", true, false, true}
6478 static int componentorder[4] = {0, 1, 2, 3};
6480 rtexture_t *R_LoadCubemap(const char *basename)
6482 int i, j, cubemapsize;
6483 unsigned char *cubemappixels, *image_buffer;
6484 rtexture_t *cubemaptexture;
6486 // must start 0 so the first loadimagepixels has no requested width/height
6488 cubemappixels = NULL;
6489 cubemaptexture = NULL;
6490 // keep trying different suffix groups (posx, px, rt) until one loads
6491 for (j = 0;j < 3 && !cubemappixels;j++)
6493 // load the 6 images in the suffix group
6494 for (i = 0;i < 6;i++)
6496 // generate an image name based on the base and and suffix
6497 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6499 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
6501 // an image loaded, make sure width and height are equal
6502 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6504 // if this is the first image to load successfully, allocate the cubemap memory
6505 if (!cubemappixels && image_width >= 1)
6507 cubemapsize = image_width;
6508 // note this clears to black, so unavailable sides are black
6509 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6511 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6513 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);
6516 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6518 Mem_Free(image_buffer);
6522 // if a cubemap loaded, upload it
6525 if (developer_loading.integer)
6526 Con_Printf("loading cubemap \"%s\"\n", basename);
6528 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6529 Mem_Free(cubemappixels);
6533 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6534 if (developer_loading.integer)
6536 Con_Printf("(tried tried images ");
6537 for (j = 0;j < 3;j++)
6538 for (i = 0;i < 6;i++)
6539 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6540 Con_Print(" and was unable to find any of them).\n");
6543 return cubemaptexture;
6546 rtexture_t *R_GetCubemap(const char *basename)
6549 for (i = 0;i < r_texture_numcubemaps;i++)
6550 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6551 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6552 if (i >= MAX_CUBEMAPS)
6553 return r_texture_whitecube;
6554 r_texture_numcubemaps++;
6555 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6556 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6557 return r_texture_cubemaps[i].texture;
6560 void R_FreeCubemaps(void)
6563 for (i = 0;i < r_texture_numcubemaps;i++)
6565 if (developer_loading.integer)
6566 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6567 if (r_texture_cubemaps[i].texture)
6568 R_FreeTexture(r_texture_cubemaps[i].texture);
6570 r_texture_numcubemaps = 0;
6573 void R_Main_FreeViewCache(void)
6575 if (r_refdef.viewcache.entityvisible)
6576 Mem_Free(r_refdef.viewcache.entityvisible);
6577 if (r_refdef.viewcache.world_pvsbits)
6578 Mem_Free(r_refdef.viewcache.world_pvsbits);
6579 if (r_refdef.viewcache.world_leafvisible)
6580 Mem_Free(r_refdef.viewcache.world_leafvisible);
6581 if (r_refdef.viewcache.world_surfacevisible)
6582 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6583 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6586 void R_Main_ResizeViewCache(void)
6588 int numentities = r_refdef.scene.numentities;
6589 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6590 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6591 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6592 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6593 if (r_refdef.viewcache.maxentities < numentities)
6595 r_refdef.viewcache.maxentities = numentities;
6596 if (r_refdef.viewcache.entityvisible)
6597 Mem_Free(r_refdef.viewcache.entityvisible);
6598 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6600 if (r_refdef.viewcache.world_numclusters != numclusters)
6602 r_refdef.viewcache.world_numclusters = numclusters;
6603 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6604 if (r_refdef.viewcache.world_pvsbits)
6605 Mem_Free(r_refdef.viewcache.world_pvsbits);
6606 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6608 if (r_refdef.viewcache.world_numleafs != numleafs)
6610 r_refdef.viewcache.world_numleafs = numleafs;
6611 if (r_refdef.viewcache.world_leafvisible)
6612 Mem_Free(r_refdef.viewcache.world_leafvisible);
6613 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6615 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6617 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6618 if (r_refdef.viewcache.world_surfacevisible)
6619 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6620 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6624 extern rtexture_t *loadingscreentexture;
6625 void gl_main_start(void)
6627 loadingscreentexture = NULL;
6628 r_texture_blanknormalmap = NULL;
6629 r_texture_white = NULL;
6630 r_texture_grey128 = NULL;
6631 r_texture_black = NULL;
6632 r_texture_whitecube = NULL;
6633 r_texture_normalizationcube = NULL;
6634 r_texture_fogattenuation = NULL;
6635 r_texture_fogheighttexture = NULL;
6636 r_texture_gammaramps = NULL;
6637 r_texture_numcubemaps = 0;
6639 r_loaddds = r_texture_dds_load.integer != 0;
6640 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6642 switch(vid.renderpath)
6644 case RENDERPATH_GL20:
6645 case RENDERPATH_D3D9:
6646 case RENDERPATH_D3D10:
6647 case RENDERPATH_D3D11:
6648 case RENDERPATH_SOFT:
6649 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6650 Cvar_SetValueQuick(&gl_combine, 1);
6651 Cvar_SetValueQuick(&r_glsl, 1);
6652 r_loadnormalmap = true;
6656 case RENDERPATH_GL13:
6657 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6658 Cvar_SetValueQuick(&gl_combine, 1);
6659 Cvar_SetValueQuick(&r_glsl, 0);
6660 r_loadnormalmap = false;
6661 r_loadgloss = false;
6664 case RENDERPATH_GL11:
6665 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6666 Cvar_SetValueQuick(&gl_combine, 0);
6667 Cvar_SetValueQuick(&r_glsl, 0);
6668 r_loadnormalmap = false;
6669 r_loadgloss = false;
6672 case RENDERPATH_GLES2:
6673 Cvar_SetValueQuick(&r_textureunits, 1);
6674 Cvar_SetValueQuick(&gl_combine, 1);
6675 Cvar_SetValueQuick(&r_glsl, 1);
6676 r_loadnormalmap = true;
6677 r_loadgloss = false;
6683 R_FrameData_Reset();
6687 memset(r_queries, 0, sizeof(r_queries));
6689 r_qwskincache = NULL;
6690 r_qwskincache_size = 0;
6692 // set up r_skinframe loading system for textures
6693 memset(&r_skinframe, 0, sizeof(r_skinframe));
6694 r_skinframe.loadsequence = 1;
6695 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6697 r_main_texturepool = R_AllocTexturePool();
6698 R_BuildBlankTextures();
6700 if (vid.support.arb_texture_cube_map)
6703 R_BuildNormalizationCube();
6705 r_texture_fogattenuation = NULL;
6706 r_texture_fogheighttexture = NULL;
6707 r_texture_gammaramps = NULL;
6708 //r_texture_fogintensity = NULL;
6709 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6710 memset(&r_waterstate, 0, sizeof(r_waterstate));
6711 r_glsl_permutation = NULL;
6712 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6713 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
6714 glslshaderstring = NULL;
6716 r_hlsl_permutation = NULL;
6717 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
6718 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
6720 hlslshaderstring = NULL;
6721 memset(&r_svbsp, 0, sizeof (r_svbsp));
6723 r_refdef.fogmasktable_density = 0;
6726 void gl_main_shutdown(void)
6729 R_FrameData_Reset();
6731 R_Main_FreeViewCache();
6733 switch(vid.renderpath)
6735 case RENDERPATH_GL11:
6736 case RENDERPATH_GL13:
6737 case RENDERPATH_GL20:
6738 case RENDERPATH_GLES2:
6740 qglDeleteQueriesARB(r_maxqueries, r_queries);
6742 case RENDERPATH_D3D9:
6743 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6745 case RENDERPATH_D3D10:
6746 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6748 case RENDERPATH_D3D11:
6749 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6751 case RENDERPATH_SOFT:
6757 memset(r_queries, 0, sizeof(r_queries));
6759 r_qwskincache = NULL;
6760 r_qwskincache_size = 0;
6762 // clear out the r_skinframe state
6763 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
6764 memset(&r_skinframe, 0, sizeof(r_skinframe));
6767 Mem_Free(r_svbsp.nodes);
6768 memset(&r_svbsp, 0, sizeof (r_svbsp));
6769 R_FreeTexturePool(&r_main_texturepool);
6770 loadingscreentexture = NULL;
6771 r_texture_blanknormalmap = NULL;
6772 r_texture_white = NULL;
6773 r_texture_grey128 = NULL;
6774 r_texture_black = NULL;
6775 r_texture_whitecube = NULL;
6776 r_texture_normalizationcube = NULL;
6777 r_texture_fogattenuation = NULL;
6778 r_texture_fogheighttexture = NULL;
6779 r_texture_gammaramps = NULL;
6780 r_texture_numcubemaps = 0;
6781 //r_texture_fogintensity = NULL;
6782 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6783 memset(&r_waterstate, 0, sizeof(r_waterstate));
6786 r_glsl_permutation = NULL;
6787 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6788 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
6789 glslshaderstring = NULL;
6791 r_hlsl_permutation = NULL;
6792 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
6793 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
6795 hlslshaderstring = NULL;
6798 extern void CL_ParseEntityLump(char *entitystring);
6799 void gl_main_newmap(void)
6801 // FIXME: move this code to client
6802 char *entities, entname[MAX_QPATH];
6804 Mem_Free(r_qwskincache);
6805 r_qwskincache = NULL;
6806 r_qwskincache_size = 0;
6809 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
6810 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
6812 CL_ParseEntityLump(entities);
6816 if (cl.worldmodel->brush.entities)
6817 CL_ParseEntityLump(cl.worldmodel->brush.entities);
6819 R_Main_FreeViewCache();
6821 R_FrameData_Reset();
6824 void GL_Main_Init(void)
6826 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
6828 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
6829 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
6830 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
6831 if (gamemode == GAME_NEHAHRA)
6833 Cvar_RegisterVariable (&gl_fogenable);
6834 Cvar_RegisterVariable (&gl_fogdensity);
6835 Cvar_RegisterVariable (&gl_fogred);
6836 Cvar_RegisterVariable (&gl_foggreen);
6837 Cvar_RegisterVariable (&gl_fogblue);
6838 Cvar_RegisterVariable (&gl_fogstart);
6839 Cvar_RegisterVariable (&gl_fogend);
6840 Cvar_RegisterVariable (&gl_skyclip);
6842 Cvar_RegisterVariable(&r_motionblur);
6843 Cvar_RegisterVariable(&r_motionblur_maxblur);
6844 Cvar_RegisterVariable(&r_motionblur_bmin);
6845 Cvar_RegisterVariable(&r_motionblur_vmin);
6846 Cvar_RegisterVariable(&r_motionblur_vmax);
6847 Cvar_RegisterVariable(&r_motionblur_vcoeff);
6848 Cvar_RegisterVariable(&r_motionblur_randomize);
6849 Cvar_RegisterVariable(&r_damageblur);
6850 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
6851 Cvar_RegisterVariable(&r_equalize_entities_minambient);
6852 Cvar_RegisterVariable(&r_equalize_entities_by);
6853 Cvar_RegisterVariable(&r_equalize_entities_to);
6854 Cvar_RegisterVariable(&r_depthfirst);
6855 Cvar_RegisterVariable(&r_useinfinitefarclip);
6856 Cvar_RegisterVariable(&r_farclip_base);
6857 Cvar_RegisterVariable(&r_farclip_world);
6858 Cvar_RegisterVariable(&r_nearclip);
6859 Cvar_RegisterVariable(&r_showbboxes);
6860 Cvar_RegisterVariable(&r_showsurfaces);
6861 Cvar_RegisterVariable(&r_showtris);
6862 Cvar_RegisterVariable(&r_shownormals);
6863 Cvar_RegisterVariable(&r_showlighting);
6864 Cvar_RegisterVariable(&r_showshadowvolumes);
6865 Cvar_RegisterVariable(&r_showcollisionbrushes);
6866 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
6867 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
6868 Cvar_RegisterVariable(&r_showdisabledepthtest);
6869 Cvar_RegisterVariable(&r_drawportals);
6870 Cvar_RegisterVariable(&r_drawentities);
6871 Cvar_RegisterVariable(&r_draw2d);
6872 Cvar_RegisterVariable(&r_drawworld);
6873 Cvar_RegisterVariable(&r_cullentities_trace);
6874 Cvar_RegisterVariable(&r_cullentities_trace_samples);
6875 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
6876 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
6877 Cvar_RegisterVariable(&r_cullentities_trace_delay);
6878 Cvar_RegisterVariable(&r_drawviewmodel);
6879 Cvar_RegisterVariable(&r_drawexteriormodel);
6880 Cvar_RegisterVariable(&r_speeds);
6881 Cvar_RegisterVariable(&r_fullbrights);
6882 Cvar_RegisterVariable(&r_wateralpha);
6883 Cvar_RegisterVariable(&r_dynamic);
6884 Cvar_RegisterVariable(&r_fakelight);
6885 Cvar_RegisterVariable(&r_fakelight_intensity);
6886 Cvar_RegisterVariable(&r_fullbright);
6887 Cvar_RegisterVariable(&r_shadows);
6888 Cvar_RegisterVariable(&r_shadows_darken);
6889 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
6890 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
6891 Cvar_RegisterVariable(&r_shadows_throwdistance);
6892 Cvar_RegisterVariable(&r_shadows_throwdirection);
6893 Cvar_RegisterVariable(&r_shadows_focus);
6894 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
6895 Cvar_RegisterVariable(&r_q1bsp_skymasking);
6896 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
6897 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
6898 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
6899 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
6900 Cvar_RegisterVariable(&r_fog_exp2);
6901 Cvar_RegisterVariable(&r_drawfog);
6902 Cvar_RegisterVariable(&r_transparentdepthmasking);
6903 Cvar_RegisterVariable(&r_texture_dds_load);
6904 Cvar_RegisterVariable(&r_texture_dds_save);
6905 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
6906 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
6907 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
6908 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
6909 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
6910 Cvar_RegisterVariable(&r_textureunits);
6911 Cvar_RegisterVariable(&gl_combine);
6912 Cvar_RegisterVariable(&r_glsl);
6913 Cvar_RegisterVariable(&r_glsl_deluxemapping);
6914 Cvar_RegisterVariable(&r_glsl_offsetmapping);
6915 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
6916 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
6917 Cvar_RegisterVariable(&r_glsl_postprocess);
6918 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
6919 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
6920 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
6921 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
6922 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
6923 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
6924 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
6925 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
6927 Cvar_RegisterVariable(&r_water);
6928 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
6929 Cvar_RegisterVariable(&r_water_clippingplanebias);
6930 Cvar_RegisterVariable(&r_water_refractdistort);
6931 Cvar_RegisterVariable(&r_water_reflectdistort);
6932 Cvar_RegisterVariable(&r_water_scissormode);
6933 Cvar_RegisterVariable(&r_lerpsprites);
6934 Cvar_RegisterVariable(&r_lerpmodels);
6935 Cvar_RegisterVariable(&r_lerplightstyles);
6936 Cvar_RegisterVariable(&r_waterscroll);
6937 Cvar_RegisterVariable(&r_bloom);
6938 Cvar_RegisterVariable(&r_bloom_colorscale);
6939 Cvar_RegisterVariable(&r_bloom_brighten);
6940 Cvar_RegisterVariable(&r_bloom_blur);
6941 Cvar_RegisterVariable(&r_bloom_resolution);
6942 Cvar_RegisterVariable(&r_bloom_colorexponent);
6943 Cvar_RegisterVariable(&r_bloom_colorsubtract);
6944 Cvar_RegisterVariable(&r_hdr);
6945 Cvar_RegisterVariable(&r_hdr_scenebrightness);
6946 Cvar_RegisterVariable(&r_hdr_glowintensity);
6947 Cvar_RegisterVariable(&r_hdr_range);
6948 Cvar_RegisterVariable(&r_hdr_irisadaptation);
6949 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
6950 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
6951 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
6952 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
6953 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
6954 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
6955 Cvar_RegisterVariable(&developer_texturelogging);
6956 Cvar_RegisterVariable(&gl_lightmaps);
6957 Cvar_RegisterVariable(&r_test);
6958 Cvar_RegisterVariable(&r_glsl_saturation);
6959 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
6960 Cvar_RegisterVariable(&r_framedatasize);
6961 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
6962 Cvar_SetValue("r_fullbrights", 0);
6963 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
6965 Cvar_RegisterVariable(&r_track_sprites);
6966 Cvar_RegisterVariable(&r_track_sprites_flags);
6967 Cvar_RegisterVariable(&r_track_sprites_scalew);
6968 Cvar_RegisterVariable(&r_track_sprites_scaleh);
6969 Cvar_RegisterVariable(&r_overheadsprites_perspective);
6970 Cvar_RegisterVariable(&r_overheadsprites_pushback);
6971 Cvar_RegisterVariable(&r_overheadsprites_scalex);
6972 Cvar_RegisterVariable(&r_overheadsprites_scaley);
6975 extern void R_Textures_Init(void);
6976 extern void GL_Draw_Init(void);
6977 extern void GL_Main_Init(void);
6978 extern void R_Shadow_Init(void);
6979 extern void R_Sky_Init(void);
6980 extern void GL_Surf_Init(void);
6981 extern void R_Particles_Init(void);
6982 extern void R_Explosion_Init(void);
6983 extern void gl_backend_init(void);
6984 extern void Sbar_Init(void);
6985 extern void R_LightningBeams_Init(void);
6986 extern void Mod_RenderInit(void);
6987 extern void Font_Init(void);
6989 void Render_Init(void)
7002 R_LightningBeams_Init();
7011 extern char *ENGINE_EXTENSIONS;
7014 gl_renderer = (const char *)qglGetString(GL_RENDERER);
7015 gl_vendor = (const char *)qglGetString(GL_VENDOR);
7016 gl_version = (const char *)qglGetString(GL_VERSION);
7017 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7021 if (!gl_platformextensions)
7022 gl_platformextensions = "";
7024 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7025 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7026 Con_Printf("GL_VERSION: %s\n", gl_version);
7027 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7028 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7030 VID_CheckExtensions();
7032 // LordHavoc: report supported extensions
7033 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7035 // clear to black (loading plaque will be seen over this)
7036 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7039 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7043 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7045 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7048 p = r_refdef.view.frustum + i;
7053 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7057 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7061 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7065 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7069 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7073 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7077 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7081 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7089 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7093 for (i = 0;i < numplanes;i++)
7100 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7104 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7108 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7112 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7116 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7120 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7124 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7128 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7136 //==================================================================================
7138 // LordHavoc: this stores temporary data used within the same frame
7140 typedef struct r_framedata_mem_s
7142 struct r_framedata_mem_s *purge; // older mem block to free on next frame
7143 size_t size; // how much usable space
7144 size_t current; // how much space in use
7145 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
7146 size_t wantedsize; // how much space was allocated
7147 unsigned char *data; // start of real data (16byte aligned)
7151 static r_framedata_mem_t *r_framedata_mem;
7153 void R_FrameData_Reset(void)
7155 while (r_framedata_mem)
7157 r_framedata_mem_t *next = r_framedata_mem->purge;
7158 Mem_Free(r_framedata_mem);
7159 r_framedata_mem = next;
7163 void R_FrameData_Resize(void)
7166 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7167 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
7168 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
7170 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
7171 newmem->wantedsize = wantedsize;
7172 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
7173 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
7174 newmem->current = 0;
7176 newmem->purge = r_framedata_mem;
7177 r_framedata_mem = newmem;
7181 void R_FrameData_NewFrame(void)
7183 R_FrameData_Resize();
7184 if (!r_framedata_mem)
7186 // if we ran out of space on the last frame, free the old memory now
7187 while (r_framedata_mem->purge)
7189 // repeatedly remove the second item in the list, leaving only head
7190 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
7191 Mem_Free(r_framedata_mem->purge);
7192 r_framedata_mem->purge = next;
7194 // reset the current mem pointer
7195 r_framedata_mem->current = 0;
7196 r_framedata_mem->mark = 0;
7199 void *R_FrameData_Alloc(size_t size)
7203 // align to 16 byte boundary - the data pointer is already aligned, so we
7204 // only need to ensure the size of every allocation is also aligned
7205 size = (size + 15) & ~15;
7207 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
7209 // emergency - we ran out of space, allocate more memory
7210 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
7211 R_FrameData_Resize();
7214 data = r_framedata_mem->data + r_framedata_mem->current;
7215 r_framedata_mem->current += size;
7217 // count the usage for stats
7218 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
7219 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
7221 return (void *)data;
7224 void *R_FrameData_Store(size_t size, void *data)
7226 void *d = R_FrameData_Alloc(size);
7228 memcpy(d, data, size);
7232 void R_FrameData_SetMark(void)
7234 if (!r_framedata_mem)
7236 r_framedata_mem->mark = r_framedata_mem->current;
7239 void R_FrameData_ReturnToMark(void)
7241 if (!r_framedata_mem)
7243 r_framedata_mem->current = r_framedata_mem->mark;
7246 //==================================================================================
7248 // LordHavoc: animcache originally written by Echon, rewritten since then
7251 * Animation cache prevents re-generating mesh data for an animated model
7252 * multiple times in one frame for lighting, shadowing, reflections, etc.
7255 void R_AnimCache_Free(void)
7259 void R_AnimCache_ClearCache(void)
7262 entity_render_t *ent;
7264 for (i = 0;i < r_refdef.scene.numentities;i++)
7266 ent = r_refdef.scene.entities[i];
7267 ent->animcache_vertex3f = NULL;
7268 ent->animcache_normal3f = NULL;
7269 ent->animcache_svector3f = NULL;
7270 ent->animcache_tvector3f = NULL;
7271 ent->animcache_vertexmesh = NULL;
7272 ent->animcache_vertex3fbuffer = NULL;
7273 ent->animcache_vertexmeshbuffer = NULL;
7277 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7281 // check if we need the meshbuffers
7282 if (!vid.useinterleavedarrays)
7285 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7286 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7287 // TODO: upload vertex3f buffer?
7288 if (ent->animcache_vertexmesh)
7290 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7291 for (i = 0;i < numvertices;i++)
7292 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7293 if (ent->animcache_svector3f)
7294 for (i = 0;i < numvertices;i++)
7295 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7296 if (ent->animcache_tvector3f)
7297 for (i = 0;i < numvertices;i++)
7298 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7299 if (ent->animcache_normal3f)
7300 for (i = 0;i < numvertices;i++)
7301 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7302 // TODO: upload vertexmeshbuffer?
7306 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7308 dp_model_t *model = ent->model;
7310 // see if it's already cached this frame
7311 if (ent->animcache_vertex3f)
7313 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7314 if (wantnormals || wanttangents)
7316 if (ent->animcache_normal3f)
7317 wantnormals = false;
7318 if (ent->animcache_svector3f)
7319 wanttangents = false;
7320 if (wantnormals || wanttangents)
7322 numvertices = model->surfmesh.num_vertices;
7324 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7327 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7328 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7330 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7331 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7337 // see if this ent is worth caching
7338 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7340 // get some memory for this entity and generate mesh data
7341 numvertices = model->surfmesh.num_vertices;
7342 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7344 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7347 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7348 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7350 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7351 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7356 void R_AnimCache_CacheVisibleEntities(void)
7359 qboolean wantnormals = true;
7360 qboolean wanttangents = !r_showsurfaces.integer;
7362 switch(vid.renderpath)
7364 case RENDERPATH_GL20:
7365 case RENDERPATH_D3D9:
7366 case RENDERPATH_D3D10:
7367 case RENDERPATH_D3D11:
7368 case RENDERPATH_GLES2:
7370 case RENDERPATH_GL13:
7371 case RENDERPATH_GL11:
7372 wanttangents = false;
7374 case RENDERPATH_SOFT:
7378 if (r_shownormals.integer)
7379 wanttangents = wantnormals = true;
7381 // TODO: thread this
7382 // NOTE: R_PrepareRTLights() also caches entities
7384 for (i = 0;i < r_refdef.scene.numentities;i++)
7385 if (r_refdef.viewcache.entityvisible[i])
7386 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7389 //==================================================================================
7391 static void R_View_UpdateEntityLighting (void)
7394 entity_render_t *ent;
7395 vec3_t tempdiffusenormal, avg;
7396 vec_t f, fa, fd, fdd;
7397 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7399 for (i = 0;i < r_refdef.scene.numentities;i++)
7401 ent = r_refdef.scene.entities[i];
7403 // skip unseen models
7404 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7408 if (ent->model && ent->model->brush.num_leafs)
7410 // TODO: use modellight for r_ambient settings on world?
7411 VectorSet(ent->modellight_ambient, 0, 0, 0);
7412 VectorSet(ent->modellight_diffuse, 0, 0, 0);
7413 VectorSet(ent->modellight_lightdir, 0, 0, 1);
7417 // fetch the lighting from the worldmodel data
7418 VectorClear(ent->modellight_ambient);
7419 VectorClear(ent->modellight_diffuse);
7420 VectorClear(tempdiffusenormal);
7421 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7424 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7426 // complete lightning for lit sprites
7427 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
7428 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
7430 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
7431 org[2] = org[2] + r_overheadsprites_pushback.value;
7432 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
7435 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
7437 if(ent->flags & RENDER_EQUALIZE)
7439 // first fix up ambient lighting...
7440 if(r_equalize_entities_minambient.value > 0)
7442 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7445 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7446 if(fa < r_equalize_entities_minambient.value * fd)
7449 // fa'/fd' = minambient
7450 // fa'+0.25*fd' = fa+0.25*fd
7452 // fa' = fd' * minambient
7453 // fd'*(0.25+minambient) = fa+0.25*fd
7455 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7456 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7458 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7459 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
7460 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7461 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7466 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7468 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
7469 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7473 // adjust brightness and saturation to target
7474 avg[0] = avg[1] = avg[2] = fa / f;
7475 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
7476 avg[0] = avg[1] = avg[2] = fd / f;
7477 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
7483 VectorSet(ent->modellight_ambient, 1, 1, 1);
7485 // move the light direction into modelspace coordinates for lighting code
7486 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7487 if(VectorLength2(ent->modellight_lightdir) == 0)
7488 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7489 VectorNormalize(ent->modellight_lightdir);
7493 #define MAX_LINEOFSIGHTTRACES 64
7495 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7498 vec3_t boxmins, boxmaxs;
7501 dp_model_t *model = r_refdef.scene.worldmodel;
7503 if (!model || !model->brush.TraceLineOfSight)
7506 // expand the box a little
7507 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7508 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7509 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7510 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7511 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7512 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7514 // return true if eye is inside enlarged box
7515 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7519 VectorCopy(eye, start);
7520 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7521 if (model->brush.TraceLineOfSight(model, start, end))
7524 // try various random positions
7525 for (i = 0;i < numsamples;i++)
7527 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7528 if (model->brush.TraceLineOfSight(model, start, end))
7536 static void R_View_UpdateEntityVisible (void)
7541 entity_render_t *ent;
7543 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7544 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7545 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
7546 : RENDER_EXTERIORMODEL;
7547 if (!r_drawviewmodel.integer)
7548 renderimask |= RENDER_VIEWMODEL;
7549 if (!r_drawexteriormodel.integer)
7550 renderimask |= RENDER_EXTERIORMODEL;
7551 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
7553 // worldmodel can check visibility
7554 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
7555 for (i = 0;i < r_refdef.scene.numentities;i++)
7557 ent = r_refdef.scene.entities[i];
7558 if (!(ent->flags & renderimask))
7559 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)))
7560 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))
7561 r_refdef.viewcache.entityvisible[i] = true;
7563 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
7564 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
7566 for (i = 0;i < r_refdef.scene.numentities;i++)
7568 ent = r_refdef.scene.entities[i];
7569 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
7571 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
7573 continue; // temp entities do pvs only
7574 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
7575 ent->last_trace_visibility = realtime;
7576 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
7577 r_refdef.viewcache.entityvisible[i] = 0;
7584 // no worldmodel or it can't check visibility
7585 for (i = 0;i < r_refdef.scene.numentities;i++)
7587 ent = r_refdef.scene.entities[i];
7588 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));
7593 /// only used if skyrendermasked, and normally returns false
7594 int R_DrawBrushModelsSky (void)
7597 entity_render_t *ent;
7600 for (i = 0;i < r_refdef.scene.numentities;i++)
7602 if (!r_refdef.viewcache.entityvisible[i])
7604 ent = r_refdef.scene.entities[i];
7605 if (!ent->model || !ent->model->DrawSky)
7607 ent->model->DrawSky(ent);
7613 static void R_DrawNoModel(entity_render_t *ent);
7614 static void R_DrawModels(void)
7617 entity_render_t *ent;
7619 for (i = 0;i < r_refdef.scene.numentities;i++)
7621 if (!r_refdef.viewcache.entityvisible[i])
7623 ent = r_refdef.scene.entities[i];
7624 r_refdef.stats.entities++;
7625 if (ent->model && ent->model->Draw != NULL)
7626 ent->model->Draw(ent);
7632 static void R_DrawModelsDepth(void)
7635 entity_render_t *ent;
7637 for (i = 0;i < r_refdef.scene.numentities;i++)
7639 if (!r_refdef.viewcache.entityvisible[i])
7641 ent = r_refdef.scene.entities[i];
7642 if (ent->model && ent->model->DrawDepth != NULL)
7643 ent->model->DrawDepth(ent);
7647 static void R_DrawModelsDebug(void)
7650 entity_render_t *ent;
7652 for (i = 0;i < r_refdef.scene.numentities;i++)
7654 if (!r_refdef.viewcache.entityvisible[i])
7656 ent = r_refdef.scene.entities[i];
7657 if (ent->model && ent->model->DrawDebug != NULL)
7658 ent->model->DrawDebug(ent);
7662 static void R_DrawModelsAddWaterPlanes(void)
7665 entity_render_t *ent;
7667 for (i = 0;i < r_refdef.scene.numentities;i++)
7669 if (!r_refdef.viewcache.entityvisible[i])
7671 ent = r_refdef.scene.entities[i];
7672 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
7673 ent->model->DrawAddWaterPlanes(ent);
7677 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
7679 if (r_hdr_irisadaptation.integer)
7683 vec3_t diffusenormal;
7688 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
7689 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
7690 brightness = max(0.0000001f, brightness);
7691 goal = r_hdr_irisadaptation_multiplier.value / brightness;
7692 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
7693 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
7694 current = r_hdr_irisadaptation_value.value;
7696 current = min(current + adjust, goal);
7697 else if (current > goal)
7698 current = max(current - adjust, goal);
7699 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
7700 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
7702 else if (r_hdr_irisadaptation_value.value != 1.0f)
7703 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
7706 static void R_View_SetFrustum(const int *scissor)
7709 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
7710 vec3_t forward, left, up, origin, v;
7714 // flipped x coordinates (because x points left here)
7715 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
7716 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
7718 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
7719 switch(vid.renderpath)
7721 case RENDERPATH_D3D9:
7722 case RENDERPATH_D3D10:
7723 case RENDERPATH_D3D11:
7724 case RENDERPATH_SOFT:
7725 // non-flipped y coordinates
7726 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7727 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7729 case RENDERPATH_GL11:
7730 case RENDERPATH_GL13:
7731 case RENDERPATH_GL20:
7732 case RENDERPATH_GLES2:
7733 // non-flipped y coordinates
7734 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7735 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7740 // we can't trust r_refdef.view.forward and friends in reflected scenes
7741 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
7744 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
7745 r_refdef.view.frustum[0].normal[1] = 0 - 0;
7746 r_refdef.view.frustum[0].normal[2] = -1 - 0;
7747 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
7748 r_refdef.view.frustum[1].normal[1] = 0 + 0;
7749 r_refdef.view.frustum[1].normal[2] = -1 + 0;
7750 r_refdef.view.frustum[2].normal[0] = 0 - 0;
7751 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
7752 r_refdef.view.frustum[2].normal[2] = -1 - 0;
7753 r_refdef.view.frustum[3].normal[0] = 0 + 0;
7754 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
7755 r_refdef.view.frustum[3].normal[2] = -1 + 0;
7759 zNear = r_refdef.nearclip;
7760 nudge = 1.0 - 1.0 / (1<<23);
7761 r_refdef.view.frustum[4].normal[0] = 0 - 0;
7762 r_refdef.view.frustum[4].normal[1] = 0 - 0;
7763 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7764 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
7765 r_refdef.view.frustum[5].normal[0] = 0 + 0;
7766 r_refdef.view.frustum[5].normal[1] = 0 + 0;
7767 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7768 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7774 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
7775 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
7776 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
7777 r_refdef.view.frustum[0].dist = m[15] - m[12];
7779 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
7780 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
7781 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
7782 r_refdef.view.frustum[1].dist = m[15] + m[12];
7784 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
7785 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
7786 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
7787 r_refdef.view.frustum[2].dist = m[15] - m[13];
7789 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
7790 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
7791 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
7792 r_refdef.view.frustum[3].dist = m[15] + m[13];
7794 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
7795 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
7796 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
7797 r_refdef.view.frustum[4].dist = m[15] - m[14];
7799 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
7800 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
7801 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
7802 r_refdef.view.frustum[5].dist = m[15] + m[14];
7805 if (r_refdef.view.useperspective)
7807 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
7808 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]);
7809 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]);
7810 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]);
7811 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]);
7813 // then the normals from the corners relative to origin
7814 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
7815 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
7816 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
7817 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
7819 // in a NORMAL view, forward cross left == up
7820 // in a REFLECTED view, forward cross left == down
7821 // so our cross products above need to be adjusted for a left handed coordinate system
7822 CrossProduct(forward, left, v);
7823 if(DotProduct(v, up) < 0)
7825 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
7826 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
7827 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
7828 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
7831 // Leaving those out was a mistake, those were in the old code, and they
7832 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
7833 // I couldn't reproduce it after adding those normalizations. --blub
7834 VectorNormalize(r_refdef.view.frustum[0].normal);
7835 VectorNormalize(r_refdef.view.frustum[1].normal);
7836 VectorNormalize(r_refdef.view.frustum[2].normal);
7837 VectorNormalize(r_refdef.view.frustum[3].normal);
7839 // make the corners absolute
7840 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
7841 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
7842 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
7843 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
7846 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7848 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
7849 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
7850 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
7851 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
7852 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7856 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
7857 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
7858 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
7859 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
7860 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7861 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
7862 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
7863 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
7864 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
7865 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7867 r_refdef.view.numfrustumplanes = 5;
7869 if (r_refdef.view.useclipplane)
7871 r_refdef.view.numfrustumplanes = 6;
7872 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
7875 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7876 PlaneClassify(r_refdef.view.frustum + i);
7878 // LordHavoc: note to all quake engine coders, Quake had a special case
7879 // for 90 degrees which assumed a square view (wrong), so I removed it,
7880 // Quake2 has it disabled as well.
7882 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
7883 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
7884 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
7885 //PlaneClassify(&frustum[0]);
7887 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
7888 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
7889 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
7890 //PlaneClassify(&frustum[1]);
7892 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
7893 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
7894 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
7895 //PlaneClassify(&frustum[2]);
7897 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
7898 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
7899 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
7900 //PlaneClassify(&frustum[3]);
7903 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
7904 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
7905 //PlaneClassify(&frustum[4]);
7908 void R_View_UpdateWithScissor(const int *myscissor)
7910 R_Main_ResizeViewCache();
7911 R_View_SetFrustum(myscissor);
7912 R_View_WorldVisibility(r_refdef.view.useclipplane);
7913 R_View_UpdateEntityVisible();
7914 R_View_UpdateEntityLighting();
7917 void R_View_Update(void)
7919 R_Main_ResizeViewCache();
7920 R_View_SetFrustum(NULL);
7921 R_View_WorldVisibility(r_refdef.view.useclipplane);
7922 R_View_UpdateEntityVisible();
7923 R_View_UpdateEntityLighting();
7926 void R_SetupView(qboolean allowwaterclippingplane)
7928 const float *customclipplane = NULL;
7930 if (r_refdef.view.useclipplane && allowwaterclippingplane)
7932 // LordHavoc: couldn't figure out how to make this approach the
7933 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
7934 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
7935 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
7936 dist = r_refdef.view.clipplane.dist;
7937 plane[0] = r_refdef.view.clipplane.normal[0];
7938 plane[1] = r_refdef.view.clipplane.normal[1];
7939 plane[2] = r_refdef.view.clipplane.normal[2];
7941 customclipplane = plane;
7944 if (!r_refdef.view.useperspective)
7945 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);
7946 else if (vid.stencil && r_useinfinitefarclip.integer)
7947 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);
7949 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);
7950 R_SetViewport(&r_refdef.view.viewport);
7953 void R_EntityMatrix(const matrix4x4_t *matrix)
7955 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
7957 gl_modelmatrixchanged = false;
7958 gl_modelmatrix = *matrix;
7959 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
7960 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
7961 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
7962 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
7964 switch(vid.renderpath)
7966 case RENDERPATH_D3D9:
7968 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
7969 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
7972 case RENDERPATH_D3D10:
7973 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
7975 case RENDERPATH_D3D11:
7976 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
7978 case RENDERPATH_GL13:
7979 case RENDERPATH_GL11:
7980 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7982 case RENDERPATH_SOFT:
7983 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
7984 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
7986 case RENDERPATH_GL20:
7987 case RENDERPATH_GLES2:
7988 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
7989 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
7995 void R_ResetViewRendering2D(void)
7997 r_viewport_t viewport;
8000 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8001 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);
8002 R_SetViewport(&viewport);
8003 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8004 GL_Color(1, 1, 1, 1);
8005 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8006 GL_BlendFunc(GL_ONE, GL_ZERO);
8007 GL_ScissorTest(false);
8008 GL_DepthMask(false);
8009 GL_DepthRange(0, 1);
8010 GL_DepthTest(false);
8011 GL_DepthFunc(GL_LEQUAL);
8012 R_EntityMatrix(&identitymatrix);
8013 R_Mesh_ResetTextureState();
8014 GL_PolygonOffset(0, 0);
8015 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8016 switch(vid.renderpath)
8018 case RENDERPATH_GL11:
8019 case RENDERPATH_GL13:
8020 case RENDERPATH_GL20:
8021 case RENDERPATH_GLES2:
8022 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8024 case RENDERPATH_D3D9:
8025 case RENDERPATH_D3D10:
8026 case RENDERPATH_D3D11:
8027 case RENDERPATH_SOFT:
8030 GL_CullFace(GL_NONE);
8033 void R_ResetViewRendering3D(void)
8038 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8039 GL_Color(1, 1, 1, 1);
8040 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8041 GL_BlendFunc(GL_ONE, GL_ZERO);
8042 GL_ScissorTest(true);
8044 GL_DepthRange(0, 1);
8046 GL_DepthFunc(GL_LEQUAL);
8047 R_EntityMatrix(&identitymatrix);
8048 R_Mesh_ResetTextureState();
8049 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8050 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8051 switch(vid.renderpath)
8053 case RENDERPATH_GL11:
8054 case RENDERPATH_GL13:
8055 case RENDERPATH_GL20:
8056 case RENDERPATH_GLES2:
8057 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8059 case RENDERPATH_D3D9:
8060 case RENDERPATH_D3D10:
8061 case RENDERPATH_D3D11:
8062 case RENDERPATH_SOFT:
8065 GL_CullFace(r_refdef.view.cullface_back);
8070 R_RenderView_UpdateViewVectors
8073 static void R_RenderView_UpdateViewVectors(void)
8075 // break apart the view matrix into vectors for various purposes
8076 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8077 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8078 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8079 VectorNegate(r_refdef.view.left, r_refdef.view.right);
8080 // make an inverted copy of the view matrix for tracking sprites
8081 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8084 void R_RenderScene(void);
8085 void R_RenderWaterPlanes(void);
8087 static void R_Water_StartFrame(void)
8090 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8091 r_waterstate_waterplane_t *p;
8093 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8096 switch(vid.renderpath)
8098 case RENDERPATH_GL20:
8099 case RENDERPATH_D3D9:
8100 case RENDERPATH_D3D10:
8101 case RENDERPATH_D3D11:
8102 case RENDERPATH_SOFT:
8103 case RENDERPATH_GLES2:
8105 case RENDERPATH_GL13:
8106 case RENDERPATH_GL11:
8110 // set waterwidth and waterheight to the water resolution that will be
8111 // used (often less than the screen resolution for faster rendering)
8112 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8113 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8115 // calculate desired texture sizes
8116 // can't use water if the card does not support the texture size
8117 if (!r_water.integer || r_showsurfaces.integer)
8118 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8119 else if (vid.support.arb_texture_non_power_of_two)
8121 texturewidth = waterwidth;
8122 textureheight = waterheight;
8123 camerawidth = waterwidth;
8124 cameraheight = waterheight;
8128 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
8129 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
8130 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
8131 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
8134 // allocate textures as needed
8135 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8137 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8138 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8140 if (p->texture_refraction)
8141 R_FreeTexture(p->texture_refraction);
8142 p->texture_refraction = NULL;
8143 if (p->texture_reflection)
8144 R_FreeTexture(p->texture_reflection);
8145 p->texture_reflection = NULL;
8146 if (p->texture_camera)
8147 R_FreeTexture(p->texture_camera);
8148 p->texture_camera = NULL;
8150 memset(&r_waterstate, 0, sizeof(r_waterstate));
8151 r_waterstate.texturewidth = texturewidth;
8152 r_waterstate.textureheight = textureheight;
8153 r_waterstate.camerawidth = camerawidth;
8154 r_waterstate.cameraheight = cameraheight;
8157 if (r_waterstate.texturewidth)
8159 r_waterstate.enabled = true;
8161 // when doing a reduced render (HDR) we want to use a smaller area
8162 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8163 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8165 // set up variables that will be used in shader setup
8166 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8167 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8168 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8169 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8172 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8173 r_waterstate.numwaterplanes = 0;
8176 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8178 int triangleindex, planeindex;
8184 r_waterstate_waterplane_t *p;
8185 texture_t *t = R_GetCurrentTexture(surface->texture);
8187 // just use the first triangle with a valid normal for any decisions
8188 VectorClear(normal);
8189 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8191 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8192 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8193 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8194 TriangleNormal(vert[0], vert[1], vert[2], normal);
8195 if (VectorLength2(normal) >= 0.001)
8199 VectorCopy(normal, plane.normal);
8200 VectorNormalize(plane.normal);
8201 plane.dist = DotProduct(vert[0], plane.normal);
8202 PlaneClassify(&plane);
8203 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8205 // skip backfaces (except if nocullface is set)
8206 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8208 VectorNegate(plane.normal, plane.normal);
8210 PlaneClassify(&plane);
8214 // find a matching plane if there is one
8215 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8216 if(p->camera_entity == t->camera_entity)
8217 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8219 if (planeindex >= r_waterstate.maxwaterplanes)
8220 return; // nothing we can do, out of planes
8222 // if this triangle does not fit any known plane rendered this frame, add one
8223 if (planeindex >= r_waterstate.numwaterplanes)
8225 // store the new plane
8226 r_waterstate.numwaterplanes++;
8228 // clear materialflags and pvs
8229 p->materialflags = 0;
8230 p->pvsvalid = false;
8231 p->camera_entity = t->camera_entity;
8232 VectorCopy(surface->mins, p->mins);
8233 VectorCopy(surface->maxs, p->maxs);
8238 p->mins[0] = min(p->mins[0], surface->mins[0]);
8239 p->mins[1] = min(p->mins[1], surface->mins[1]);
8240 p->mins[2] = min(p->mins[2], surface->mins[2]);
8241 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8242 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8243 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8245 // merge this surface's materialflags into the waterplane
8246 p->materialflags |= t->currentmaterialflags;
8247 if(!(p->materialflags & MATERIALFLAG_CAMERA))
8249 // merge this surface's PVS into the waterplane
8250 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8251 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8252 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8254 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8260 static void R_Water_ProcessPlanes(void)
8263 r_refdef_view_t originalview;
8264 r_refdef_view_t myview;
8266 r_waterstate_waterplane_t *p;
8269 originalview = r_refdef.view;
8271 // make sure enough textures are allocated
8272 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8274 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8276 if (!p->texture_refraction)
8277 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);
8278 if (!p->texture_refraction)
8281 else if (p->materialflags & MATERIALFLAG_CAMERA)
8283 if (!p->texture_camera)
8284 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);
8285 if (!p->texture_camera)
8289 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8291 if (!p->texture_reflection)
8292 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);
8293 if (!p->texture_reflection)
8299 r_refdef.view = originalview;
8300 r_refdef.view.showdebug = false;
8301 r_refdef.view.width = r_waterstate.waterwidth;
8302 r_refdef.view.height = r_waterstate.waterheight;
8303 r_refdef.view.useclipplane = true;
8304 myview = r_refdef.view;
8305 r_waterstate.renderingscene = true;
8306 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8308 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8310 r_refdef.view = myview;
8311 if(r_water_scissormode.integer)
8314 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8315 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8318 // render reflected scene and copy into texture
8319 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8320 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8321 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8322 r_refdef.view.clipplane = p->plane;
8324 // reverse the cullface settings for this render
8325 r_refdef.view.cullface_front = GL_FRONT;
8326 r_refdef.view.cullface_back = GL_BACK;
8327 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8329 r_refdef.view.usecustompvs = true;
8331 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8333 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8336 R_ResetViewRendering3D();
8337 R_ClearScreen(r_refdef.fogenabled);
8338 if(r_water_scissormode.integer & 2)
8339 R_View_UpdateWithScissor(myscissor);
8342 if(r_water_scissormode.integer & 1)
8343 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8346 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);
8349 // render the normal view scene and copy into texture
8350 // (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)
8351 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8353 r_refdef.view = myview;
8354 if(r_water_scissormode.integer)
8357 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8358 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8361 r_waterstate.renderingrefraction = true;
8363 r_refdef.view.clipplane = p->plane;
8364 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8365 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8367 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8369 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8370 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8371 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8372 R_RenderView_UpdateViewVectors();
8373 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8375 r_refdef.view.usecustompvs = true;
8376 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);
8380 PlaneClassify(&r_refdef.view.clipplane);
8382 R_ResetViewRendering3D();
8383 R_ClearScreen(r_refdef.fogenabled);
8384 if(r_water_scissormode.integer & 2)
8385 R_View_UpdateWithScissor(myscissor);
8388 if(r_water_scissormode.integer & 1)
8389 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8392 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);
8393 r_waterstate.renderingrefraction = false;
8395 else if (p->materialflags & MATERIALFLAG_CAMERA)
8397 r_refdef.view = myview;
8399 r_refdef.view.clipplane = p->plane;
8400 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8401 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8403 r_refdef.view.width = r_waterstate.camerawidth;
8404 r_refdef.view.height = r_waterstate.cameraheight;
8405 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8406 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8408 if(p->camera_entity)
8410 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8411 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8414 // note: all of the view is used for displaying... so
8415 // there is no use in scissoring
8417 // reverse the cullface settings for this render
8418 r_refdef.view.cullface_front = GL_FRONT;
8419 r_refdef.view.cullface_back = GL_BACK;
8420 // also reverse the view matrix
8421 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
8422 R_RenderView_UpdateViewVectors();
8423 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8425 r_refdef.view.usecustompvs = true;
8426 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);
8429 // camera needs no clipplane
8430 r_refdef.view.useclipplane = false;
8432 PlaneClassify(&r_refdef.view.clipplane);
8434 R_ResetViewRendering3D();
8435 R_ClearScreen(r_refdef.fogenabled);
8439 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);
8440 r_waterstate.renderingrefraction = false;
8444 r_waterstate.renderingscene = false;
8445 r_refdef.view = originalview;
8446 R_ResetViewRendering3D();
8447 R_ClearScreen(r_refdef.fogenabled);
8451 r_refdef.view = originalview;
8452 r_waterstate.renderingscene = false;
8453 Cvar_SetValueQuick(&r_water, 0);
8454 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
8458 void R_Bloom_StartFrame(void)
8460 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8462 switch(vid.renderpath)
8464 case RENDERPATH_GL20:
8465 case RENDERPATH_D3D9:
8466 case RENDERPATH_D3D10:
8467 case RENDERPATH_D3D11:
8468 case RENDERPATH_SOFT:
8469 case RENDERPATH_GLES2:
8471 case RENDERPATH_GL13:
8472 case RENDERPATH_GL11:
8476 // set bloomwidth and bloomheight to the bloom resolution that will be
8477 // used (often less than the screen resolution for faster rendering)
8478 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8479 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8480 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8481 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8482 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8484 // calculate desired texture sizes
8485 if (vid.support.arb_texture_non_power_of_two)
8487 screentexturewidth = r_refdef.view.width;
8488 screentextureheight = r_refdef.view.height;
8489 bloomtexturewidth = r_bloomstate.bloomwidth;
8490 bloomtextureheight = r_bloomstate.bloomheight;
8494 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
8495 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
8496 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
8497 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
8500 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))
8502 Cvar_SetValueQuick(&r_hdr, 0);
8503 Cvar_SetValueQuick(&r_bloom, 0);
8504 Cvar_SetValueQuick(&r_motionblur, 0);
8505 Cvar_SetValueQuick(&r_damageblur, 0);
8508 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)))
8509 screentexturewidth = screentextureheight = 0;
8510 if (!r_hdr.integer && !r_bloom.integer)
8511 bloomtexturewidth = bloomtextureheight = 0;
8513 // allocate textures as needed
8514 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8516 if (r_bloomstate.texture_screen)
8517 R_FreeTexture(r_bloomstate.texture_screen);
8518 r_bloomstate.texture_screen = NULL;
8519 r_bloomstate.screentexturewidth = screentexturewidth;
8520 r_bloomstate.screentextureheight = screentextureheight;
8521 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8522 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);
8524 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8526 if (r_bloomstate.texture_bloom)
8527 R_FreeTexture(r_bloomstate.texture_bloom);
8528 r_bloomstate.texture_bloom = NULL;
8529 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8530 r_bloomstate.bloomtextureheight = bloomtextureheight;
8531 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8532 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);
8535 // when doing a reduced render (HDR) we want to use a smaller area
8536 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8537 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8538 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8539 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8540 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8542 // set up a texcoord array for the full resolution screen image
8543 // (we have to keep this around to copy back during final render)
8544 r_bloomstate.screentexcoord2f[0] = 0;
8545 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
8546 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
8547 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
8548 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
8549 r_bloomstate.screentexcoord2f[5] = 0;
8550 r_bloomstate.screentexcoord2f[6] = 0;
8551 r_bloomstate.screentexcoord2f[7] = 0;
8553 // set up a texcoord array for the reduced resolution bloom image
8554 // (which will be additive blended over the screen image)
8555 r_bloomstate.bloomtexcoord2f[0] = 0;
8556 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8557 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8558 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8559 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8560 r_bloomstate.bloomtexcoord2f[5] = 0;
8561 r_bloomstate.bloomtexcoord2f[6] = 0;
8562 r_bloomstate.bloomtexcoord2f[7] = 0;
8564 switch(vid.renderpath)
8566 case RENDERPATH_GL11:
8567 case RENDERPATH_GL13:
8568 case RENDERPATH_GL20:
8569 case RENDERPATH_SOFT:
8570 case RENDERPATH_GLES2:
8572 case RENDERPATH_D3D9:
8573 case RENDERPATH_D3D10:
8574 case RENDERPATH_D3D11:
8577 for (i = 0;i < 4;i++)
8579 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
8580 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
8581 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
8582 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
8588 if (r_hdr.integer || r_bloom.integer)
8590 r_bloomstate.enabled = true;
8591 r_bloomstate.hdr = r_hdr.integer != 0;
8594 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);
8597 void R_Bloom_CopyBloomTexture(float colorscale)
8599 r_refdef.stats.bloom++;
8601 // scale down screen texture to the bloom texture size
8603 R_SetViewport(&r_bloomstate.viewport);
8604 GL_BlendFunc(GL_ONE, GL_ZERO);
8605 GL_Color(colorscale, colorscale, colorscale, 1);
8606 // 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...
8607 switch(vid.renderpath)
8609 case RENDERPATH_GL11:
8610 case RENDERPATH_GL13:
8611 case RENDERPATH_GL20:
8612 case RENDERPATH_SOFT:
8613 case RENDERPATH_GLES2:
8614 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8616 case RENDERPATH_D3D9:
8617 case RENDERPATH_D3D10:
8618 case RENDERPATH_D3D11:
8619 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8622 // TODO: do boxfilter scale-down in shader?
8623 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8624 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8625 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8627 // we now have a bloom image in the framebuffer
8628 // copy it into the bloom image texture for later processing
8629 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);
8630 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8633 void R_Bloom_CopyHDRTexture(void)
8635 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);
8636 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8639 void R_Bloom_MakeTexture(void)
8642 float xoffset, yoffset, r, brighten;
8644 r_refdef.stats.bloom++;
8646 R_ResetViewRendering2D();
8648 // we have a bloom image in the framebuffer
8650 R_SetViewport(&r_bloomstate.viewport);
8652 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
8655 r = bound(0, r_bloom_colorexponent.value / x, 1);
8656 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
8658 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
8659 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8660 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8661 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8663 // copy the vertically blurred bloom view to a texture
8664 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);
8665 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8668 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
8669 brighten = r_bloom_brighten.value;
8671 brighten *= r_hdr_range.value;
8672 brighten = sqrt(brighten);
8674 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
8675 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8677 for (dir = 0;dir < 2;dir++)
8679 // blend on at multiple vertical offsets to achieve a vertical blur
8680 // TODO: do offset blends using GLSL
8681 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
8682 GL_BlendFunc(GL_ONE, GL_ZERO);
8683 for (x = -range;x <= range;x++)
8685 if (!dir){xoffset = 0;yoffset = x;}
8686 else {xoffset = x;yoffset = 0;}
8687 xoffset /= (float)r_bloomstate.bloomtexturewidth;
8688 yoffset /= (float)r_bloomstate.bloomtextureheight;
8689 // compute a texcoord array with the specified x and y offset
8690 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
8691 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8692 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8693 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8694 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8695 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
8696 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
8697 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
8698 // this r value looks like a 'dot' particle, fading sharply to
8699 // black at the edges
8700 // (probably not realistic but looks good enough)
8701 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
8702 //r = brighten/(range*2+1);
8703 r = brighten / (range * 2 + 1);
8705 r *= (1 - x*x/(float)(range*range));
8706 GL_Color(r, r, r, 1);
8707 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
8708 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8709 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8710 GL_BlendFunc(GL_ONE, GL_ONE);
8713 // copy the vertically blurred bloom view to a texture
8714 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);
8715 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8719 void R_HDR_RenderBloomTexture(void)
8721 int oldwidth, oldheight;
8722 float oldcolorscale;
8723 qboolean oldwaterstate;
8725 oldwaterstate = r_waterstate.enabled;
8726 oldcolorscale = r_refdef.view.colorscale;
8727 oldwidth = r_refdef.view.width;
8728 oldheight = r_refdef.view.height;
8729 r_refdef.view.width = r_bloomstate.bloomwidth;
8730 r_refdef.view.height = r_bloomstate.bloomheight;
8732 if(r_hdr.integer < 2)
8733 r_waterstate.enabled = false;
8735 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
8736 // TODO: add exposure compensation features
8737 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
8739 r_refdef.view.showdebug = false;
8740 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
8742 R_ResetViewRendering3D();
8744 R_ClearScreen(r_refdef.fogenabled);
8745 if (r_timereport_active)
8746 R_TimeReport("HDRclear");
8749 if (r_timereport_active)
8750 R_TimeReport("visibility");
8752 // only do secondary renders with HDR if r_hdr is 2 or higher
8753 r_waterstate.numwaterplanes = 0;
8754 if (r_waterstate.enabled)
8755 R_RenderWaterPlanes();
8757 r_refdef.view.showdebug = true;
8759 r_waterstate.numwaterplanes = 0;
8761 R_ResetViewRendering2D();
8763 R_Bloom_CopyHDRTexture();
8764 R_Bloom_MakeTexture();
8766 // restore the view settings
8767 r_waterstate.enabled = oldwaterstate;
8768 r_refdef.view.width = oldwidth;
8769 r_refdef.view.height = oldheight;
8770 r_refdef.view.colorscale = oldcolorscale;
8772 R_ResetViewRendering3D();
8774 R_ClearScreen(r_refdef.fogenabled);
8775 if (r_timereport_active)
8776 R_TimeReport("viewclear");
8779 static void R_BlendView(void)
8781 unsigned int permutation;
8782 float uservecs[4][4];
8784 switch (vid.renderpath)
8786 case RENDERPATH_GL20:
8787 case RENDERPATH_D3D9:
8788 case RENDERPATH_D3D10:
8789 case RENDERPATH_D3D11:
8790 case RENDERPATH_SOFT:
8791 case RENDERPATH_GLES2:
8793 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
8794 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
8795 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
8796 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
8797 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
8799 if (r_bloomstate.texture_screen)
8801 // make sure the buffer is available
8802 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
8804 R_ResetViewRendering2D();
8806 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
8808 // declare variables
8810 static float avgspeed;
8812 speed = VectorLength(cl.movement_velocity);
8814 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
8815 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
8817 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
8818 speed = bound(0, speed, 1);
8819 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
8821 // calculate values into a standard alpha
8822 cl.motionbluralpha = 1 - exp(-
8824 (r_motionblur.value * speed / 80)
8826 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
8829 max(0.0001, cl.time - cl.oldtime) // fps independent
8832 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
8833 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
8835 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
8837 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8838 GL_Color(1, 1, 1, cl.motionbluralpha);
8839 switch(vid.renderpath)
8841 case RENDERPATH_GL11:
8842 case RENDERPATH_GL13:
8843 case RENDERPATH_GL20:
8844 case RENDERPATH_SOFT:
8845 case RENDERPATH_GLES2:
8846 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8848 case RENDERPATH_D3D9:
8849 case RENDERPATH_D3D10:
8850 case RENDERPATH_D3D11:
8851 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8854 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8855 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8856 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8860 // copy view into the screen texture
8861 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);
8862 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8864 else if (!r_bloomstate.texture_bloom)
8866 // we may still have to do view tint...
8867 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8869 // apply a color tint to the whole view
8870 R_ResetViewRendering2D();
8871 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8872 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
8873 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8874 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8875 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8877 break; // no screen processing, no bloom, skip it
8880 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
8882 // render simple bloom effect
8883 // copy the screen and shrink it and darken it for the bloom process
8884 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
8885 // make the bloom texture
8886 R_Bloom_MakeTexture();
8889 #if _MSC_VER >= 1400
8890 #define sscanf sscanf_s
8892 memset(uservecs, 0, sizeof(uservecs));
8893 if (r_glsl_postprocess_uservec1_enable.integer)
8894 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
8895 if (r_glsl_postprocess_uservec2_enable.integer)
8896 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
8897 if (r_glsl_postprocess_uservec3_enable.integer)
8898 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
8899 if (r_glsl_postprocess_uservec4_enable.integer)
8900 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
8902 R_ResetViewRendering2D();
8903 GL_Color(1, 1, 1, 1);
8904 GL_BlendFunc(GL_ONE, GL_ZERO);
8906 switch(vid.renderpath)
8908 case RENDERPATH_GL20:
8909 case RENDERPATH_GLES2:
8910 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8911 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
8912 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
8913 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
8914 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
8915 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]);
8916 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8917 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]);
8918 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]);
8919 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]);
8920 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]);
8921 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
8922 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8923 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);
8925 case RENDERPATH_D3D9:
8927 // 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...
8928 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8929 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
8930 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
8931 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
8932 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
8933 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8934 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8935 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
8936 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
8937 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
8938 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
8939 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
8940 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
8941 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
8944 case RENDERPATH_D3D10:
8945 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
8947 case RENDERPATH_D3D11:
8948 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
8950 case RENDERPATH_SOFT:
8951 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8952 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
8953 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
8954 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
8955 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
8956 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8957 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8958 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
8959 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
8960 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
8961 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
8962 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
8963 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8964 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
8969 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8970 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8972 case RENDERPATH_GL13:
8973 case RENDERPATH_GL11:
8974 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8976 // apply a color tint to the whole view
8977 R_ResetViewRendering2D();
8978 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8979 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
8980 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8981 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8982 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8988 matrix4x4_t r_waterscrollmatrix;
8990 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
8992 if (r_refdef.fog_density)
8994 r_refdef.fogcolor[0] = r_refdef.fog_red;
8995 r_refdef.fogcolor[1] = r_refdef.fog_green;
8996 r_refdef.fogcolor[2] = r_refdef.fog_blue;
8998 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
8999 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9000 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9001 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9005 VectorCopy(r_refdef.fogcolor, fogvec);
9006 // color.rgb *= ContrastBoost * SceneBrightness;
9007 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9008 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9009 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9010 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9015 void R_UpdateVariables(void)
9019 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9021 r_refdef.farclip = r_farclip_base.value;
9022 if (r_refdef.scene.worldmodel)
9023 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9024 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9026 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9027 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9028 r_refdef.polygonfactor = 0;
9029 r_refdef.polygonoffset = 0;
9030 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9031 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9033 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9034 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9035 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
9036 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9037 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9038 if (FAKELIGHT_ENABLED)
9040 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
9042 if (r_showsurfaces.integer)
9044 r_refdef.scene.rtworld = false;
9045 r_refdef.scene.rtworldshadows = false;
9046 r_refdef.scene.rtdlight = false;
9047 r_refdef.scene.rtdlightshadows = false;
9048 r_refdef.lightmapintensity = 0;
9051 if (gamemode == GAME_NEHAHRA)
9053 if (gl_fogenable.integer)
9055 r_refdef.oldgl_fogenable = true;
9056 r_refdef.fog_density = gl_fogdensity.value;
9057 r_refdef.fog_red = gl_fogred.value;
9058 r_refdef.fog_green = gl_foggreen.value;
9059 r_refdef.fog_blue = gl_fogblue.value;
9060 r_refdef.fog_alpha = 1;
9061 r_refdef.fog_start = 0;
9062 r_refdef.fog_end = gl_skyclip.value;
9063 r_refdef.fog_height = 1<<30;
9064 r_refdef.fog_fadedepth = 128;
9066 else if (r_refdef.oldgl_fogenable)
9068 r_refdef.oldgl_fogenable = false;
9069 r_refdef.fog_density = 0;
9070 r_refdef.fog_red = 0;
9071 r_refdef.fog_green = 0;
9072 r_refdef.fog_blue = 0;
9073 r_refdef.fog_alpha = 0;
9074 r_refdef.fog_start = 0;
9075 r_refdef.fog_end = 0;
9076 r_refdef.fog_height = 1<<30;
9077 r_refdef.fog_fadedepth = 128;
9081 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9082 r_refdef.fog_start = max(0, r_refdef.fog_start);
9083 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9085 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9087 if (r_refdef.fog_density && r_drawfog.integer)
9089 r_refdef.fogenabled = true;
9090 // this is the point where the fog reaches 0.9986 alpha, which we
9091 // consider a good enough cutoff point for the texture
9092 // (0.9986 * 256 == 255.6)
9093 if (r_fog_exp2.integer)
9094 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9096 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9097 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9098 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9099 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9100 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9101 R_BuildFogHeightTexture();
9102 // fog color was already set
9103 // update the fog texture
9104 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)
9105 R_BuildFogTexture();
9106 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9107 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9110 r_refdef.fogenabled = false;
9112 switch(vid.renderpath)
9114 case RENDERPATH_GL20:
9115 case RENDERPATH_D3D9:
9116 case RENDERPATH_D3D10:
9117 case RENDERPATH_D3D11:
9118 case RENDERPATH_SOFT:
9119 case RENDERPATH_GLES2:
9120 if(v_glslgamma.integer && !vid_gammatables_trivial)
9122 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9124 // build GLSL gamma texture
9125 #define RAMPWIDTH 256
9126 unsigned short ramp[RAMPWIDTH * 3];
9127 unsigned char rampbgr[RAMPWIDTH][4];
9130 r_texture_gammaramps_serial = vid_gammatables_serial;
9132 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9133 for(i = 0; i < RAMPWIDTH; ++i)
9135 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9136 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9137 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9140 if (r_texture_gammaramps)
9142 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9146 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9152 // remove GLSL gamma texture
9155 case RENDERPATH_GL13:
9156 case RENDERPATH_GL11:
9161 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9162 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9168 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9169 if( scenetype != r_currentscenetype ) {
9170 // store the old scenetype
9171 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9172 r_currentscenetype = scenetype;
9173 // move in the new scene
9174 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9183 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9185 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9186 if( scenetype == r_currentscenetype ) {
9187 return &r_refdef.scene;
9189 return &r_scenes_store[ scenetype ];
9198 int dpsoftrast_test;
9199 void R_RenderView(void)
9201 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
9203 dpsoftrast_test = r_test.integer;
9205 if (r_timereport_active)
9206 R_TimeReport("start");
9207 r_textureframe++; // used only by R_GetCurrentTexture
9208 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9210 if(R_CompileShader_CheckStaticParms())
9213 if (!r_drawentities.integer)
9214 r_refdef.scene.numentities = 0;
9216 R_AnimCache_ClearCache();
9217 R_FrameData_NewFrame();
9219 /* adjust for stereo display */
9220 if(R_Stereo_Active())
9222 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);
9223 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
9226 if (r_refdef.view.isoverlay)
9228 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9229 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9230 R_TimeReport("depthclear");
9232 r_refdef.view.showdebug = false;
9234 r_waterstate.enabled = false;
9235 r_waterstate.numwaterplanes = 0;
9239 r_refdef.view.matrix = originalmatrix;
9245 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9247 r_refdef.view.matrix = originalmatrix;
9248 return; //Host_Error ("R_RenderView: NULL worldmodel");
9251 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
9253 R_RenderView_UpdateViewVectors();
9255 R_Shadow_UpdateWorldLightSelection();
9257 R_Bloom_StartFrame();
9258 R_Water_StartFrame();
9261 if (r_timereport_active)
9262 R_TimeReport("viewsetup");
9264 R_ResetViewRendering3D();
9266 if (r_refdef.view.clear || r_refdef.fogenabled)
9268 R_ClearScreen(r_refdef.fogenabled);
9269 if (r_timereport_active)
9270 R_TimeReport("viewclear");
9272 r_refdef.view.clear = true;
9274 // this produces a bloom texture to be used in R_BlendView() later
9275 if (r_hdr.integer && r_bloomstate.bloomwidth)
9277 R_HDR_RenderBloomTexture();
9278 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9279 r_textureframe++; // used only by R_GetCurrentTexture
9282 r_refdef.view.showdebug = true;
9285 if (r_timereport_active)
9286 R_TimeReport("visibility");
9288 r_waterstate.numwaterplanes = 0;
9289 if (r_waterstate.enabled)
9290 R_RenderWaterPlanes();
9293 r_waterstate.numwaterplanes = 0;
9296 if (r_timereport_active)
9297 R_TimeReport("blendview");
9299 GL_Scissor(0, 0, vid.width, vid.height);
9300 GL_ScissorTest(false);
9302 r_refdef.view.matrix = originalmatrix;
9307 void R_RenderWaterPlanes(void)
9309 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9311 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9312 if (r_timereport_active)
9313 R_TimeReport("waterworld");
9316 // don't let sound skip if going slow
9317 if (r_refdef.scene.extraupdate)
9320 R_DrawModelsAddWaterPlanes();
9321 if (r_timereport_active)
9322 R_TimeReport("watermodels");
9324 if (r_waterstate.numwaterplanes)
9326 R_Water_ProcessPlanes();
9327 if (r_timereport_active)
9328 R_TimeReport("waterscenes");
9332 extern void R_DrawLightningBeams (void);
9333 extern void VM_CL_AddPolygonsToMeshQueue (void);
9334 extern void R_DrawPortals (void);
9335 extern cvar_t cl_locs_show;
9336 static void R_DrawLocs(void);
9337 static void R_DrawEntityBBoxes(void);
9338 static void R_DrawModelDecals(void);
9339 extern void R_DrawModelShadows(void);
9340 extern void R_DrawModelShadowMaps(void);
9341 extern cvar_t cl_decals_newsystem;
9342 extern qboolean r_shadow_usingdeferredprepass;
9343 void R_RenderScene(void)
9345 qboolean shadowmapping = false;
9347 if (r_timereport_active)
9348 R_TimeReport("beginscene");
9350 r_refdef.stats.renders++;
9354 // don't let sound skip if going slow
9355 if (r_refdef.scene.extraupdate)
9358 R_MeshQueue_BeginScene();
9362 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);
9364 if (r_timereport_active)
9365 R_TimeReport("skystartframe");
9367 if (cl.csqc_vidvars.drawworld)
9369 // don't let sound skip if going slow
9370 if (r_refdef.scene.extraupdate)
9373 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9375 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9376 if (r_timereport_active)
9377 R_TimeReport("worldsky");
9380 if (R_DrawBrushModelsSky() && r_timereport_active)
9381 R_TimeReport("bmodelsky");
9383 if (skyrendermasked && skyrenderlater)
9385 // we have to force off the water clipping plane while rendering sky
9389 if (r_timereport_active)
9390 R_TimeReport("sky");
9394 R_AnimCache_CacheVisibleEntities();
9395 if (r_timereport_active)
9396 R_TimeReport("animation");
9398 R_Shadow_PrepareLights();
9399 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9400 R_Shadow_PrepareModelShadows();
9401 if (r_timereport_active)
9402 R_TimeReport("preparelights");
9404 if (R_Shadow_ShadowMappingEnabled())
9405 shadowmapping = true;
9407 if (r_shadow_usingdeferredprepass)
9408 R_Shadow_DrawPrepass();
9410 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9412 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9413 if (r_timereport_active)
9414 R_TimeReport("worlddepth");
9416 if (r_depthfirst.integer >= 2)
9418 R_DrawModelsDepth();
9419 if (r_timereport_active)
9420 R_TimeReport("modeldepth");
9423 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9425 R_DrawModelShadowMaps();
9426 R_ResetViewRendering3D();
9427 // don't let sound skip if going slow
9428 if (r_refdef.scene.extraupdate)
9432 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9434 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9435 if (r_timereport_active)
9436 R_TimeReport("world");
9439 // don't let sound skip if going slow
9440 if (r_refdef.scene.extraupdate)
9444 if (r_timereport_active)
9445 R_TimeReport("models");
9447 // don't let sound skip if going slow
9448 if (r_refdef.scene.extraupdate)
9451 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9453 R_DrawModelShadows();
9454 R_ResetViewRendering3D();
9455 // don't let sound skip if going slow
9456 if (r_refdef.scene.extraupdate)
9460 if (!r_shadow_usingdeferredprepass)
9462 R_Shadow_DrawLights();
9463 if (r_timereport_active)
9464 R_TimeReport("rtlights");
9467 // don't let sound skip if going slow
9468 if (r_refdef.scene.extraupdate)
9471 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9473 R_DrawModelShadows();
9474 R_ResetViewRendering3D();
9475 // don't let sound skip if going slow
9476 if (r_refdef.scene.extraupdate)
9480 if (cl.csqc_vidvars.drawworld)
9482 if (cl_decals_newsystem.integer)
9484 R_DrawModelDecals();
9485 if (r_timereport_active)
9486 R_TimeReport("modeldecals");
9491 if (r_timereport_active)
9492 R_TimeReport("decals");
9496 if (r_timereport_active)
9497 R_TimeReport("particles");
9500 if (r_timereport_active)
9501 R_TimeReport("explosions");
9503 R_DrawLightningBeams();
9504 if (r_timereport_active)
9505 R_TimeReport("lightning");
9508 VM_CL_AddPolygonsToMeshQueue();
9510 if (r_refdef.view.showdebug)
9512 if (cl_locs_show.integer)
9515 if (r_timereport_active)
9516 R_TimeReport("showlocs");
9519 if (r_drawportals.integer)
9522 if (r_timereport_active)
9523 R_TimeReport("portals");
9526 if (r_showbboxes.value > 0)
9528 R_DrawEntityBBoxes();
9529 if (r_timereport_active)
9530 R_TimeReport("bboxes");
9534 R_MeshQueue_RenderTransparent();
9535 if (r_timereport_active)
9536 R_TimeReport("drawtrans");
9538 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))
9540 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9541 if (r_timereport_active)
9542 R_TimeReport("worlddebug");
9543 R_DrawModelsDebug();
9544 if (r_timereport_active)
9545 R_TimeReport("modeldebug");
9548 if (cl.csqc_vidvars.drawworld)
9550 R_Shadow_DrawCoronas();
9551 if (r_timereport_active)
9552 R_TimeReport("coronas");
9557 GL_DepthTest(false);
9558 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9559 GL_Color(1, 1, 1, 1);
9560 qglBegin(GL_POLYGON);
9561 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
9562 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
9563 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
9564 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
9566 qglBegin(GL_POLYGON);
9567 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]);
9568 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]);
9569 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]);
9570 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]);
9572 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9576 // don't let sound skip if going slow
9577 if (r_refdef.scene.extraupdate)
9580 R_ResetViewRendering2D();
9583 static const unsigned short bboxelements[36] =
9593 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9596 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9598 RSurf_ActiveWorldEntity();
9600 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9601 GL_DepthMask(false);
9602 GL_DepthRange(0, 1);
9603 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9604 // R_Mesh_ResetTextureState();
9606 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9607 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9608 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9609 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9610 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9611 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9612 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9613 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9614 R_FillColors(color4f, 8, cr, cg, cb, ca);
9615 if (r_refdef.fogenabled)
9617 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9619 f1 = RSurf_FogVertex(v);
9621 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9622 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9623 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9626 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
9627 R_Mesh_ResetTextureState();
9628 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9629 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
9632 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9636 prvm_edict_t *edict;
9637 prvm_prog_t *prog_save = prog;
9639 // this function draws bounding boxes of server entities
9643 GL_CullFace(GL_NONE);
9644 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9648 for (i = 0;i < numsurfaces;i++)
9650 edict = PRVM_EDICT_NUM(surfacelist[i]);
9651 switch ((int)edict->fields.server->solid)
9653 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
9654 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
9655 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
9656 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9657 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
9658 default: Vector4Set(color, 0, 0, 0, 0.50);break;
9660 color[3] *= r_showbboxes.value;
9661 color[3] = bound(0, color[3], 1);
9662 GL_DepthTest(!r_showdisabledepthtest.integer);
9663 GL_CullFace(r_refdef.view.cullface_front);
9664 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
9670 static void R_DrawEntityBBoxes(void)
9673 prvm_edict_t *edict;
9675 prvm_prog_t *prog_save = prog;
9677 // this function draws bounding boxes of server entities
9683 for (i = 0;i < prog->num_edicts;i++)
9685 edict = PRVM_EDICT_NUM(i);
9686 if (edict->priv.server->free)
9688 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
9689 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
9691 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
9693 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
9694 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
9700 static const int nomodelelement3i[24] =
9712 static const unsigned short nomodelelement3s[24] =
9724 static const float nomodelvertex3f[6*3] =
9734 static const float nomodelcolor4f[6*4] =
9736 0.0f, 0.0f, 0.5f, 1.0f,
9737 0.0f, 0.0f, 0.5f, 1.0f,
9738 0.0f, 0.5f, 0.0f, 1.0f,
9739 0.0f, 0.5f, 0.0f, 1.0f,
9740 0.5f, 0.0f, 0.0f, 1.0f,
9741 0.5f, 0.0f, 0.0f, 1.0f
9744 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9750 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);
9752 // this is only called once per entity so numsurfaces is always 1, and
9753 // surfacelist is always {0}, so this code does not handle batches
9755 if (rsurface.ent_flags & RENDER_ADDITIVE)
9757 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
9758 GL_DepthMask(false);
9760 else if (rsurface.colormod[3] < 1)
9762 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9763 GL_DepthMask(false);
9767 GL_BlendFunc(GL_ONE, GL_ZERO);
9770 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
9771 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
9772 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
9773 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
9774 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
9775 for (i = 0, c = color4f;i < 6;i++, c += 4)
9777 c[0] *= rsurface.colormod[0];
9778 c[1] *= rsurface.colormod[1];
9779 c[2] *= rsurface.colormod[2];
9780 c[3] *= rsurface.colormod[3];
9782 if (r_refdef.fogenabled)
9784 for (i = 0, c = color4f;i < 6;i++, c += 4)
9786 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
9788 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
9789 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
9790 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
9793 // R_Mesh_ResetTextureState();
9794 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9795 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
9796 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
9799 void R_DrawNoModel(entity_render_t *ent)
9802 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
9803 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
9804 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
9806 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
9809 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
9811 vec3_t right1, right2, diff, normal;
9813 VectorSubtract (org2, org1, normal);
9815 // calculate 'right' vector for start
9816 VectorSubtract (r_refdef.view.origin, org1, diff);
9817 CrossProduct (normal, diff, right1);
9818 VectorNormalize (right1);
9820 // calculate 'right' vector for end
9821 VectorSubtract (r_refdef.view.origin, org2, diff);
9822 CrossProduct (normal, diff, right2);
9823 VectorNormalize (right2);
9825 vert[ 0] = org1[0] + width * right1[0];
9826 vert[ 1] = org1[1] + width * right1[1];
9827 vert[ 2] = org1[2] + width * right1[2];
9828 vert[ 3] = org1[0] - width * right1[0];
9829 vert[ 4] = org1[1] - width * right1[1];
9830 vert[ 5] = org1[2] - width * right1[2];
9831 vert[ 6] = org2[0] - width * right2[0];
9832 vert[ 7] = org2[1] - width * right2[1];
9833 vert[ 8] = org2[2] - width * right2[2];
9834 vert[ 9] = org2[0] + width * right2[0];
9835 vert[10] = org2[1] + width * right2[1];
9836 vert[11] = org2[2] + width * right2[2];
9839 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)
9841 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
9842 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
9843 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
9844 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
9845 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
9846 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
9847 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
9848 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
9849 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
9850 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
9851 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
9852 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
9855 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
9860 VectorSet(v, x, y, z);
9861 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
9862 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
9864 if (i == mesh->numvertices)
9866 if (mesh->numvertices < mesh->maxvertices)
9868 VectorCopy(v, vertex3f);
9869 mesh->numvertices++;
9871 return mesh->numvertices;
9877 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
9881 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9882 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9883 e = mesh->element3i + mesh->numtriangles * 3;
9884 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
9886 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
9887 if (mesh->numtriangles < mesh->maxtriangles)
9892 mesh->numtriangles++;
9894 element[1] = element[2];
9898 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
9902 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9903 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9904 e = mesh->element3i + mesh->numtriangles * 3;
9905 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
9907 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
9908 if (mesh->numtriangles < mesh->maxtriangles)
9913 mesh->numtriangles++;
9915 element[1] = element[2];
9919 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
9920 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
9922 int planenum, planenum2;
9925 mplane_t *plane, *plane2;
9927 double temppoints[2][256*3];
9928 // figure out how large a bounding box we need to properly compute this brush
9930 for (w = 0;w < numplanes;w++)
9931 maxdist = max(maxdist, fabs(planes[w].dist));
9932 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
9933 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
9934 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
9938 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
9939 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
9941 if (planenum2 == planenum)
9943 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);
9946 if (tempnumpoints < 3)
9948 // generate elements forming a triangle fan for this polygon
9949 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
9953 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)
9955 texturelayer_t *layer;
9956 layer = t->currentlayers + t->currentnumlayers++;
9958 layer->depthmask = depthmask;
9959 layer->blendfunc1 = blendfunc1;
9960 layer->blendfunc2 = blendfunc2;
9961 layer->texture = texture;
9962 layer->texmatrix = *matrix;
9963 layer->color[0] = r;
9964 layer->color[1] = g;
9965 layer->color[2] = b;
9966 layer->color[3] = a;
9969 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
9971 if(parms[0] == 0 && parms[1] == 0)
9973 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
9974 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
9979 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
9982 index = parms[2] + r_refdef.scene.time * parms[3];
9983 index -= floor(index);
9984 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
9987 case Q3WAVEFUNC_NONE:
9988 case Q3WAVEFUNC_NOISE:
9989 case Q3WAVEFUNC_COUNT:
9992 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
9993 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
9994 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
9995 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
9996 case Q3WAVEFUNC_TRIANGLE:
9998 f = index - floor(index);
10001 else if (index < 2)
10003 else if (index < 3)
10009 f = parms[0] + parms[1] * f;
10010 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10011 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10015 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10020 matrix4x4_t matrix, temp;
10021 switch(tcmod->tcmod)
10023 case Q3TCMOD_COUNT:
10025 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10026 matrix = r_waterscrollmatrix;
10028 matrix = identitymatrix;
10030 case Q3TCMOD_ENTITYTRANSLATE:
10031 // this is used in Q3 to allow the gamecode to control texcoord
10032 // scrolling on the entity, which is not supported in darkplaces yet.
10033 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10035 case Q3TCMOD_ROTATE:
10036 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10037 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10038 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10040 case Q3TCMOD_SCALE:
10041 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10043 case Q3TCMOD_SCROLL:
10044 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10046 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10047 w = (int) tcmod->parms[0];
10048 h = (int) tcmod->parms[1];
10049 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10051 idx = (int) floor(f * w * h);
10052 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10054 case Q3TCMOD_STRETCH:
10055 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10056 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10058 case Q3TCMOD_TRANSFORM:
10059 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
10060 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
10061 VectorSet(tcmat + 6, 0 , 0 , 1);
10062 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
10063 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10065 case Q3TCMOD_TURBULENT:
10066 // this is handled in the RSurf_PrepareVertices function
10067 matrix = identitymatrix;
10071 Matrix4x4_Concat(texmatrix, &matrix, &temp);
10074 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10076 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10077 char name[MAX_QPATH];
10078 skinframe_t *skinframe;
10079 unsigned char pixels[296*194];
10080 strlcpy(cache->name, skinname, sizeof(cache->name));
10081 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10082 if (developer_loading.integer)
10083 Con_Printf("loading %s\n", name);
10084 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10085 if (!skinframe || !skinframe->base)
10088 fs_offset_t filesize;
10090 f = FS_LoadFile(name, tempmempool, true, &filesize);
10093 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10094 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10098 cache->skinframe = skinframe;
10101 texture_t *R_GetCurrentTexture(texture_t *t)
10104 const entity_render_t *ent = rsurface.entity;
10105 dp_model_t *model = ent->model;
10106 q3shaderinfo_layer_tcmod_t *tcmod;
10108 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10109 return t->currentframe;
10110 t->update_lastrenderframe = r_textureframe;
10111 t->update_lastrenderentity = (void *)ent;
10113 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10114 t->camera_entity = ent->entitynumber;
10116 t->camera_entity = 0;
10118 // switch to an alternate material if this is a q1bsp animated material
10120 texture_t *texture = t;
10121 int s = rsurface.ent_skinnum;
10122 if ((unsigned int)s >= (unsigned int)model->numskins)
10124 if (model->skinscenes)
10126 if (model->skinscenes[s].framecount > 1)
10127 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10129 s = model->skinscenes[s].firstframe;
10132 t = t + s * model->num_surfaces;
10135 // use an alternate animation if the entity's frame is not 0,
10136 // and only if the texture has an alternate animation
10137 if (rsurface.ent_alttextures && t->anim_total[1])
10138 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10140 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10142 texture->currentframe = t;
10145 // update currentskinframe to be a qw skin or animation frame
10146 if (rsurface.ent_qwskin >= 0)
10148 i = rsurface.ent_qwskin;
10149 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10151 r_qwskincache_size = cl.maxclients;
10153 Mem_Free(r_qwskincache);
10154 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10156 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10157 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10158 t->currentskinframe = r_qwskincache[i].skinframe;
10159 if (t->currentskinframe == NULL)
10160 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10162 else if (t->numskinframes >= 2)
10163 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10164 if (t->backgroundnumskinframes >= 2)
10165 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10167 t->currentmaterialflags = t->basematerialflags;
10168 t->currentalpha = rsurface.colormod[3];
10169 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10170 t->currentalpha *= r_wateralpha.value;
10171 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10172 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10173 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10174 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10175 if (!(rsurface.ent_flags & RENDER_LIGHT))
10176 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10177 else if (FAKELIGHT_ENABLED)
10179 // no modellight if using fakelight for the map
10181 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10183 // pick a model lighting mode
10184 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10185 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10187 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10189 if (rsurface.ent_flags & RENDER_ADDITIVE)
10190 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10191 else if (t->currentalpha < 1)
10192 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10193 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10194 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10195 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10196 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10197 if (t->backgroundnumskinframes)
10198 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10199 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10201 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10202 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10205 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10206 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10207 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10209 // there is no tcmod
10210 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10212 t->currenttexmatrix = r_waterscrollmatrix;
10213 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10215 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10217 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10218 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10221 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10222 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10223 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10224 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10226 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10227 if (t->currentskinframe->qpixels)
10228 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10229 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10230 if (!t->basetexture)
10231 t->basetexture = r_texture_notexture;
10232 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10233 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10234 t->nmaptexture = t->currentskinframe->nmap;
10235 if (!t->nmaptexture)
10236 t->nmaptexture = r_texture_blanknormalmap;
10237 t->glosstexture = r_texture_black;
10238 t->glowtexture = t->currentskinframe->glow;
10239 t->fogtexture = t->currentskinframe->fog;
10240 t->reflectmasktexture = t->currentskinframe->reflect;
10241 if (t->backgroundnumskinframes)
10243 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10244 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10245 t->backgroundglosstexture = r_texture_black;
10246 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10247 if (!t->backgroundnmaptexture)
10248 t->backgroundnmaptexture = r_texture_blanknormalmap;
10252 t->backgroundbasetexture = r_texture_white;
10253 t->backgroundnmaptexture = r_texture_blanknormalmap;
10254 t->backgroundglosstexture = r_texture_black;
10255 t->backgroundglowtexture = NULL;
10257 t->specularpower = r_shadow_glossexponent.value;
10258 // TODO: store reference values for these in the texture?
10259 t->specularscale = 0;
10260 if (r_shadow_gloss.integer > 0)
10262 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10264 if (r_shadow_glossintensity.value > 0)
10266 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10267 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10268 t->specularscale = r_shadow_glossintensity.value;
10271 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10273 t->glosstexture = r_texture_white;
10274 t->backgroundglosstexture = r_texture_white;
10275 t->specularscale = r_shadow_gloss2intensity.value;
10276 t->specularpower = r_shadow_gloss2exponent.value;
10279 t->specularscale *= t->specularscalemod;
10280 t->specularpower *= t->specularpowermod;
10282 // lightmaps mode looks bad with dlights using actual texturing, so turn
10283 // off the colormap and glossmap, but leave the normalmap on as it still
10284 // accurately represents the shading involved
10285 if (gl_lightmaps.integer)
10287 t->basetexture = r_texture_grey128;
10288 t->pantstexture = r_texture_black;
10289 t->shirttexture = r_texture_black;
10290 t->nmaptexture = r_texture_blanknormalmap;
10291 t->glosstexture = r_texture_black;
10292 t->glowtexture = NULL;
10293 t->fogtexture = NULL;
10294 t->reflectmasktexture = NULL;
10295 t->backgroundbasetexture = NULL;
10296 t->backgroundnmaptexture = r_texture_blanknormalmap;
10297 t->backgroundglosstexture = r_texture_black;
10298 t->backgroundglowtexture = NULL;
10299 t->specularscale = 0;
10300 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10303 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10304 VectorClear(t->dlightcolor);
10305 t->currentnumlayers = 0;
10306 if (t->currentmaterialflags & MATERIALFLAG_WALL)
10308 int blendfunc1, blendfunc2;
10309 qboolean depthmask;
10310 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10312 blendfunc1 = GL_SRC_ALPHA;
10313 blendfunc2 = GL_ONE;
10315 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10317 blendfunc1 = GL_SRC_ALPHA;
10318 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10320 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10322 blendfunc1 = t->customblendfunc[0];
10323 blendfunc2 = t->customblendfunc[1];
10327 blendfunc1 = GL_ONE;
10328 blendfunc2 = GL_ZERO;
10330 // don't colormod evilblend textures
10331 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10332 VectorSet(t->lightmapcolor, 1, 1, 1);
10333 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10334 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10336 // fullbright is not affected by r_refdef.lightmapintensity
10337 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]);
10338 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10339 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]);
10340 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10341 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]);
10345 vec3_t ambientcolor;
10347 // set the color tint used for lights affecting this surface
10348 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10350 // q3bsp has no lightmap updates, so the lightstylevalue that
10351 // would normally be baked into the lightmap must be
10352 // applied to the color
10353 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10354 if (model->type == mod_brushq3)
10355 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10356 colorscale *= r_refdef.lightmapintensity;
10357 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10358 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10359 // basic lit geometry
10360 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]);
10361 // add pants/shirt if needed
10362 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10363 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]);
10364 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10365 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]);
10366 // now add ambient passes if needed
10367 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10369 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]);
10370 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10371 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]);
10372 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10373 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]);
10376 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10377 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]);
10378 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10380 // if this is opaque use alpha blend which will darken the earlier
10383 // if this is an alpha blended material, all the earlier passes
10384 // were darkened by fog already, so we only need to add the fog
10385 // color ontop through the fog mask texture
10387 // if this is an additive blended material, all the earlier passes
10388 // were darkened by fog already, and we should not add fog color
10389 // (because the background was not darkened, there is no fog color
10390 // that was lost behind it).
10391 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]);
10395 return t->currentframe;
10398 rsurfacestate_t rsurface;
10400 void RSurf_ActiveWorldEntity(void)
10402 dp_model_t *model = r_refdef.scene.worldmodel;
10403 //if (rsurface.entity == r_refdef.scene.worldentity)
10405 rsurface.entity = r_refdef.scene.worldentity;
10406 rsurface.skeleton = NULL;
10407 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10408 rsurface.ent_skinnum = 0;
10409 rsurface.ent_qwskin = -1;
10410 rsurface.ent_shadertime = 0;
10411 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10412 rsurface.matrix = identitymatrix;
10413 rsurface.inversematrix = identitymatrix;
10414 rsurface.matrixscale = 1;
10415 rsurface.inversematrixscale = 1;
10416 R_EntityMatrix(&identitymatrix);
10417 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10418 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10419 rsurface.fograngerecip = r_refdef.fograngerecip;
10420 rsurface.fogheightfade = r_refdef.fogheightfade;
10421 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10422 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10423 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10424 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10425 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10426 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10427 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10428 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10429 rsurface.colormod[3] = 1;
10430 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);
10431 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10432 rsurface.frameblend[0].lerp = 1;
10433 rsurface.ent_alttextures = false;
10434 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10435 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10436 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
10437 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10438 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10439 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10440 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10441 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10442 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10443 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10444 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10445 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
10446 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10447 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10448 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
10449 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10450 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10451 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
10452 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10453 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10454 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
10455 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10456 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10457 rsurface.modelelement3i = model->surfmesh.data_element3i;
10458 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10459 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10460 rsurface.modelelement3s = model->surfmesh.data_element3s;
10461 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10462 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10463 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10464 rsurface.modelnumvertices = model->surfmesh.num_vertices;
10465 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10466 rsurface.modelsurfaces = model->data_surfaces;
10467 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10468 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10469 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
10470 rsurface.modelgeneratedvertex = false;
10471 rsurface.batchgeneratedvertex = false;
10472 rsurface.batchfirstvertex = 0;
10473 rsurface.batchnumvertices = 0;
10474 rsurface.batchfirsttriangle = 0;
10475 rsurface.batchnumtriangles = 0;
10476 rsurface.batchvertex3f = NULL;
10477 rsurface.batchvertex3f_vertexbuffer = NULL;
10478 rsurface.batchvertex3f_bufferoffset = 0;
10479 rsurface.batchsvector3f = NULL;
10480 rsurface.batchsvector3f_vertexbuffer = NULL;
10481 rsurface.batchsvector3f_bufferoffset = 0;
10482 rsurface.batchtvector3f = NULL;
10483 rsurface.batchtvector3f_vertexbuffer = NULL;
10484 rsurface.batchtvector3f_bufferoffset = 0;
10485 rsurface.batchnormal3f = NULL;
10486 rsurface.batchnormal3f_vertexbuffer = NULL;
10487 rsurface.batchnormal3f_bufferoffset = 0;
10488 rsurface.batchlightmapcolor4f = NULL;
10489 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10490 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10491 rsurface.batchtexcoordtexture2f = NULL;
10492 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10493 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10494 rsurface.batchtexcoordlightmap2f = NULL;
10495 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10496 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10497 rsurface.batchvertexmesh = NULL;
10498 rsurface.batchvertexmeshbuffer = NULL;
10499 rsurface.batchvertex3fbuffer = NULL;
10500 rsurface.batchelement3i = NULL;
10501 rsurface.batchelement3i_indexbuffer = NULL;
10502 rsurface.batchelement3i_bufferoffset = 0;
10503 rsurface.batchelement3s = NULL;
10504 rsurface.batchelement3s_indexbuffer = NULL;
10505 rsurface.batchelement3s_bufferoffset = 0;
10506 rsurface.passcolor4f = NULL;
10507 rsurface.passcolor4f_vertexbuffer = NULL;
10508 rsurface.passcolor4f_bufferoffset = 0;
10511 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10513 dp_model_t *model = ent->model;
10514 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10516 rsurface.entity = (entity_render_t *)ent;
10517 rsurface.skeleton = ent->skeleton;
10518 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10519 rsurface.ent_skinnum = ent->skinnum;
10520 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;
10521 rsurface.ent_shadertime = ent->shadertime;
10522 rsurface.ent_flags = ent->flags;
10523 rsurface.matrix = ent->matrix;
10524 rsurface.inversematrix = ent->inversematrix;
10525 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10526 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10527 R_EntityMatrix(&rsurface.matrix);
10528 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10529 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10530 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10531 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10532 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10533 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10534 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10535 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10536 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10537 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10538 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10539 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10540 rsurface.colormod[3] = ent->alpha;
10541 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10542 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10543 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10544 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10545 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10546 if (ent->model->brush.submodel && !prepass)
10548 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10549 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10551 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10553 if (ent->animcache_vertex3f)
10555 rsurface.modelvertex3f = ent->animcache_vertex3f;
10556 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10557 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10558 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10559 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
10560 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
10561 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
10563 else if (wanttangents)
10565 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10566 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10567 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10568 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10569 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
10570 rsurface.modelvertexmesh = NULL;
10571 rsurface.modelvertexmeshbuffer = NULL;
10572 rsurface.modelvertex3fbuffer = NULL;
10574 else if (wantnormals)
10576 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10577 rsurface.modelsvector3f = NULL;
10578 rsurface.modeltvector3f = NULL;
10579 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10580 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
10581 rsurface.modelvertexmesh = NULL;
10582 rsurface.modelvertexmeshbuffer = NULL;
10583 rsurface.modelvertex3fbuffer = NULL;
10587 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10588 rsurface.modelsvector3f = NULL;
10589 rsurface.modeltvector3f = NULL;
10590 rsurface.modelnormal3f = NULL;
10591 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
10592 rsurface.modelvertexmesh = NULL;
10593 rsurface.modelvertexmeshbuffer = NULL;
10594 rsurface.modelvertex3fbuffer = NULL;
10596 rsurface.modelvertex3f_vertexbuffer = 0;
10597 rsurface.modelvertex3f_bufferoffset = 0;
10598 rsurface.modelsvector3f_vertexbuffer = 0;
10599 rsurface.modelsvector3f_bufferoffset = 0;
10600 rsurface.modeltvector3f_vertexbuffer = 0;
10601 rsurface.modeltvector3f_bufferoffset = 0;
10602 rsurface.modelnormal3f_vertexbuffer = 0;
10603 rsurface.modelnormal3f_bufferoffset = 0;
10604 rsurface.modelgeneratedvertex = true;
10608 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
10609 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10610 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10611 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10612 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10613 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10614 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10615 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10616 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10617 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
10618 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10619 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10620 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10621 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10622 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
10623 rsurface.modelgeneratedvertex = false;
10625 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
10626 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10627 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10628 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
10629 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10630 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10631 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
10632 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10633 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10634 rsurface.modelelement3i = model->surfmesh.data_element3i;
10635 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10636 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10637 rsurface.modelelement3s = model->surfmesh.data_element3s;
10638 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10639 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10640 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10641 rsurface.modelnumvertices = model->surfmesh.num_vertices;
10642 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10643 rsurface.modelsurfaces = model->data_surfaces;
10644 rsurface.batchgeneratedvertex = false;
10645 rsurface.batchfirstvertex = 0;
10646 rsurface.batchnumvertices = 0;
10647 rsurface.batchfirsttriangle = 0;
10648 rsurface.batchnumtriangles = 0;
10649 rsurface.batchvertex3f = NULL;
10650 rsurface.batchvertex3f_vertexbuffer = NULL;
10651 rsurface.batchvertex3f_bufferoffset = 0;
10652 rsurface.batchsvector3f = NULL;
10653 rsurface.batchsvector3f_vertexbuffer = NULL;
10654 rsurface.batchsvector3f_bufferoffset = 0;
10655 rsurface.batchtvector3f = NULL;
10656 rsurface.batchtvector3f_vertexbuffer = NULL;
10657 rsurface.batchtvector3f_bufferoffset = 0;
10658 rsurface.batchnormal3f = NULL;
10659 rsurface.batchnormal3f_vertexbuffer = NULL;
10660 rsurface.batchnormal3f_bufferoffset = 0;
10661 rsurface.batchlightmapcolor4f = NULL;
10662 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10663 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10664 rsurface.batchtexcoordtexture2f = NULL;
10665 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10666 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10667 rsurface.batchtexcoordlightmap2f = NULL;
10668 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10669 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10670 rsurface.batchvertexmesh = NULL;
10671 rsurface.batchvertexmeshbuffer = NULL;
10672 rsurface.batchvertex3fbuffer = NULL;
10673 rsurface.batchelement3i = NULL;
10674 rsurface.batchelement3i_indexbuffer = NULL;
10675 rsurface.batchelement3i_bufferoffset = 0;
10676 rsurface.batchelement3s = NULL;
10677 rsurface.batchelement3s_indexbuffer = NULL;
10678 rsurface.batchelement3s_bufferoffset = 0;
10679 rsurface.passcolor4f = NULL;
10680 rsurface.passcolor4f_vertexbuffer = NULL;
10681 rsurface.passcolor4f_bufferoffset = 0;
10684 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)
10686 rsurface.entity = r_refdef.scene.worldentity;
10687 rsurface.skeleton = NULL;
10688 rsurface.ent_skinnum = 0;
10689 rsurface.ent_qwskin = -1;
10690 rsurface.ent_shadertime = shadertime;
10691 rsurface.ent_flags = entflags;
10692 rsurface.modelnumvertices = numvertices;
10693 rsurface.modelnumtriangles = numtriangles;
10694 rsurface.matrix = *matrix;
10695 rsurface.inversematrix = *inversematrix;
10696 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10697 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10698 R_EntityMatrix(&rsurface.matrix);
10699 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10700 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10701 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10702 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10703 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10704 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10705 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10706 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10707 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10708 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10709 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10710 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
10711 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);
10712 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10713 rsurface.frameblend[0].lerp = 1;
10714 rsurface.ent_alttextures = false;
10715 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10716 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10719 rsurface.modelvertex3f = (float *)vertex3f;
10720 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10721 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10722 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10724 else if (wantnormals)
10726 rsurface.modelvertex3f = (float *)vertex3f;
10727 rsurface.modelsvector3f = NULL;
10728 rsurface.modeltvector3f = NULL;
10729 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10733 rsurface.modelvertex3f = (float *)vertex3f;
10734 rsurface.modelsvector3f = NULL;
10735 rsurface.modeltvector3f = NULL;
10736 rsurface.modelnormal3f = NULL;
10738 rsurface.modelvertexmesh = NULL;
10739 rsurface.modelvertexmeshbuffer = NULL;
10740 rsurface.modelvertex3fbuffer = NULL;
10741 rsurface.modelvertex3f_vertexbuffer = 0;
10742 rsurface.modelvertex3f_bufferoffset = 0;
10743 rsurface.modelsvector3f_vertexbuffer = 0;
10744 rsurface.modelsvector3f_bufferoffset = 0;
10745 rsurface.modeltvector3f_vertexbuffer = 0;
10746 rsurface.modeltvector3f_bufferoffset = 0;
10747 rsurface.modelnormal3f_vertexbuffer = 0;
10748 rsurface.modelnormal3f_bufferoffset = 0;
10749 rsurface.modelgeneratedvertex = true;
10750 rsurface.modellightmapcolor4f = (float *)color4f;
10751 rsurface.modellightmapcolor4f_vertexbuffer = 0;
10752 rsurface.modellightmapcolor4f_bufferoffset = 0;
10753 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
10754 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
10755 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
10756 rsurface.modeltexcoordlightmap2f = NULL;
10757 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
10758 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
10759 rsurface.modelelement3i = (int *)element3i;
10760 rsurface.modelelement3i_indexbuffer = NULL;
10761 rsurface.modelelement3i_bufferoffset = 0;
10762 rsurface.modelelement3s = (unsigned short *)element3s;
10763 rsurface.modelelement3s_indexbuffer = NULL;
10764 rsurface.modelelement3s_bufferoffset = 0;
10765 rsurface.modellightmapoffsets = NULL;
10766 rsurface.modelsurfaces = NULL;
10767 rsurface.batchgeneratedvertex = false;
10768 rsurface.batchfirstvertex = 0;
10769 rsurface.batchnumvertices = 0;
10770 rsurface.batchfirsttriangle = 0;
10771 rsurface.batchnumtriangles = 0;
10772 rsurface.batchvertex3f = NULL;
10773 rsurface.batchvertex3f_vertexbuffer = NULL;
10774 rsurface.batchvertex3f_bufferoffset = 0;
10775 rsurface.batchsvector3f = NULL;
10776 rsurface.batchsvector3f_vertexbuffer = NULL;
10777 rsurface.batchsvector3f_bufferoffset = 0;
10778 rsurface.batchtvector3f = NULL;
10779 rsurface.batchtvector3f_vertexbuffer = NULL;
10780 rsurface.batchtvector3f_bufferoffset = 0;
10781 rsurface.batchnormal3f = NULL;
10782 rsurface.batchnormal3f_vertexbuffer = NULL;
10783 rsurface.batchnormal3f_bufferoffset = 0;
10784 rsurface.batchlightmapcolor4f = NULL;
10785 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10786 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10787 rsurface.batchtexcoordtexture2f = NULL;
10788 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10789 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10790 rsurface.batchtexcoordlightmap2f = NULL;
10791 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10792 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10793 rsurface.batchvertexmesh = NULL;
10794 rsurface.batchvertexmeshbuffer = NULL;
10795 rsurface.batchvertex3fbuffer = NULL;
10796 rsurface.batchelement3i = NULL;
10797 rsurface.batchelement3i_indexbuffer = NULL;
10798 rsurface.batchelement3i_bufferoffset = 0;
10799 rsurface.batchelement3s = NULL;
10800 rsurface.batchelement3s_indexbuffer = NULL;
10801 rsurface.batchelement3s_bufferoffset = 0;
10802 rsurface.passcolor4f = NULL;
10803 rsurface.passcolor4f_vertexbuffer = NULL;
10804 rsurface.passcolor4f_bufferoffset = 0;
10806 if (rsurface.modelnumvertices && rsurface.modelelement3i)
10808 if ((wantnormals || wanttangents) && !normal3f)
10810 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10811 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
10813 if (wanttangents && !svector3f)
10815 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10816 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10817 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
10822 float RSurf_FogPoint(const float *v)
10824 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10825 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
10826 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
10827 float FogHeightFade = r_refdef.fogheightfade;
10829 unsigned int fogmasktableindex;
10830 if (r_refdef.fogplaneviewabove)
10831 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10833 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10834 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
10835 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10838 float RSurf_FogVertex(const float *v)
10840 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10841 float FogPlaneViewDist = rsurface.fogplaneviewdist;
10842 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
10843 float FogHeightFade = rsurface.fogheightfade;
10845 unsigned int fogmasktableindex;
10846 if (r_refdef.fogplaneviewabove)
10847 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10849 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10850 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
10851 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10854 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
10857 for (i = 0;i < numelements;i++)
10858 outelement3i[i] = inelement3i[i] + adjust;
10861 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
10862 extern cvar_t gl_vbo;
10863 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
10871 int surfacefirsttriangle;
10872 int surfacenumtriangles;
10873 int surfacefirstvertex;
10874 int surfaceendvertex;
10875 int surfacenumvertices;
10876 int batchnumvertices;
10877 int batchnumtriangles;
10881 qboolean dynamicvertex;
10885 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
10886 float waveparms[4];
10887 q3shaderinfo_deform_t *deform;
10888 const msurface_t *surface, *firstsurface;
10889 r_vertexmesh_t *vertexmesh;
10890 if (!texturenumsurfaces)
10892 // find vertex range of this surface batch
10894 firstsurface = texturesurfacelist[0];
10895 firsttriangle = firstsurface->num_firsttriangle;
10896 batchnumvertices = 0;
10897 batchnumtriangles = 0;
10898 firstvertex = endvertex = firstsurface->num_firstvertex;
10899 for (i = 0;i < texturenumsurfaces;i++)
10901 surface = texturesurfacelist[i];
10902 if (surface != firstsurface + i)
10904 surfacefirstvertex = surface->num_firstvertex;
10905 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
10906 surfacenumvertices = surface->num_vertices;
10907 surfacenumtriangles = surface->num_triangles;
10908 if (firstvertex > surfacefirstvertex)
10909 firstvertex = surfacefirstvertex;
10910 if (endvertex < surfaceendvertex)
10911 endvertex = surfaceendvertex;
10912 batchnumvertices += surfacenumvertices;
10913 batchnumtriangles += surfacenumtriangles;
10916 // we now know the vertex range used, and if there are any gaps in it
10917 rsurface.batchfirstvertex = firstvertex;
10918 rsurface.batchnumvertices = endvertex - firstvertex;
10919 rsurface.batchfirsttriangle = firsttriangle;
10920 rsurface.batchnumtriangles = batchnumtriangles;
10922 // this variable holds flags for which properties have been updated that
10923 // may require regenerating vertexmesh array...
10926 // check if any dynamic vertex processing must occur
10927 dynamicvertex = false;
10929 // if there is a chance of animated vertex colors, it's a dynamic batch
10930 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
10932 dynamicvertex = true;
10933 batchneed |= BATCHNEED_NOGAPS;
10934 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
10937 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
10939 switch (deform->deform)
10942 case Q3DEFORM_PROJECTIONSHADOW:
10943 case Q3DEFORM_TEXT0:
10944 case Q3DEFORM_TEXT1:
10945 case Q3DEFORM_TEXT2:
10946 case Q3DEFORM_TEXT3:
10947 case Q3DEFORM_TEXT4:
10948 case Q3DEFORM_TEXT5:
10949 case Q3DEFORM_TEXT6:
10950 case Q3DEFORM_TEXT7:
10951 case Q3DEFORM_NONE:
10953 case Q3DEFORM_AUTOSPRITE:
10954 dynamicvertex = true;
10955 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10956 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10958 case Q3DEFORM_AUTOSPRITE2:
10959 dynamicvertex = true;
10960 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10961 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10963 case Q3DEFORM_NORMAL:
10964 dynamicvertex = true;
10965 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10966 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10968 case Q3DEFORM_WAVE:
10969 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10970 break; // if wavefunc is a nop, ignore this transform
10971 dynamicvertex = true;
10972 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10973 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10975 case Q3DEFORM_BULGE:
10976 dynamicvertex = true;
10977 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10978 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10980 case Q3DEFORM_MOVE:
10981 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10982 break; // if wavefunc is a nop, ignore this transform
10983 dynamicvertex = true;
10984 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
10985 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
10989 switch(rsurface.texture->tcgen.tcgen)
10992 case Q3TCGEN_TEXTURE:
10994 case Q3TCGEN_LIGHTMAP:
10995 dynamicvertex = true;
10996 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
10997 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
10999 case Q3TCGEN_VECTOR:
11000 dynamicvertex = true;
11001 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11002 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11004 case Q3TCGEN_ENVIRONMENT:
11005 dynamicvertex = true;
11006 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11007 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11010 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11012 dynamicvertex = true;
11013 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11014 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11017 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11019 dynamicvertex = true;
11020 batchneed |= BATCHNEED_NOGAPS;
11021 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11024 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11026 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11027 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
11028 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
11029 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
11030 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11031 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11032 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11035 // when the model data has no vertex buffer (dynamic mesh), we need to
11037 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
11038 batchneed |= BATCHNEED_NOGAPS;
11040 // if needsupdate, we have to do a dynamic vertex batch for sure
11041 if (needsupdate & batchneed)
11042 dynamicvertex = true;
11044 // see if we need to build vertexmesh from arrays
11045 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11046 dynamicvertex = true;
11048 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11049 // also some drivers strongly dislike firstvertex
11050 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11051 dynamicvertex = true;
11053 rsurface.batchvertex3f = rsurface.modelvertex3f;
11054 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11055 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11056 rsurface.batchsvector3f = rsurface.modelsvector3f;
11057 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11058 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11059 rsurface.batchtvector3f = rsurface.modeltvector3f;
11060 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11061 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11062 rsurface.batchnormal3f = rsurface.modelnormal3f;
11063 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11064 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11065 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11066 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
11067 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11068 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11069 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
11070 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
11071 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11072 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11073 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11074 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
11075 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11076 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11077 rsurface.batchelement3i = rsurface.modelelement3i;
11078 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11079 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11080 rsurface.batchelement3s = rsurface.modelelement3s;
11081 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11082 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11084 // if any dynamic vertex processing has to occur in software, we copy the
11085 // entire surface list together before processing to rebase the vertices
11086 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11088 // if any gaps exist and we do not have a static vertex buffer, we have to
11089 // copy the surface list together to avoid wasting upload bandwidth on the
11090 // vertices in the gaps.
11092 // if gaps exist and we have a static vertex buffer, we still have to
11093 // combine the index buffer ranges into one dynamic index buffer.
11095 // in all cases we end up with data that can be drawn in one call.
11097 if (!dynamicvertex)
11099 // static vertex data, just set pointers...
11100 rsurface.batchgeneratedvertex = false;
11101 // if there are gaps, we want to build a combined index buffer,
11102 // otherwise use the original static buffer with an appropriate offset
11105 // build a new triangle elements array for this batch
11106 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11107 rsurface.batchfirsttriangle = 0;
11109 for (i = 0;i < texturenumsurfaces;i++)
11111 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11112 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11113 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11114 numtriangles += surfacenumtriangles;
11116 rsurface.batchelement3i_indexbuffer = NULL;
11117 rsurface.batchelement3i_bufferoffset = 0;
11118 rsurface.batchelement3s = NULL;
11119 rsurface.batchelement3s_indexbuffer = NULL;
11120 rsurface.batchelement3s_bufferoffset = 0;
11121 if (endvertex <= 65536)
11123 // make a 16bit (unsigned short) index array if possible
11124 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11125 for (i = 0;i < numtriangles*3;i++)
11126 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11132 // something needs software processing, do it for real...
11133 // we only directly handle separate array data in this case and then
11134 // generate interleaved data if needed...
11135 rsurface.batchgeneratedvertex = true;
11137 // now copy the vertex data into a combined array and make an index array
11138 // (this is what Quake3 does all the time)
11139 //if (gaps || rsurface.batchfirstvertex)
11141 rsurface.batchvertex3fbuffer = NULL;
11142 rsurface.batchvertexmesh = NULL;
11143 rsurface.batchvertexmeshbuffer = NULL;
11144 rsurface.batchvertex3f = NULL;
11145 rsurface.batchvertex3f_vertexbuffer = NULL;
11146 rsurface.batchvertex3f_bufferoffset = 0;
11147 rsurface.batchsvector3f = NULL;
11148 rsurface.batchsvector3f_vertexbuffer = NULL;
11149 rsurface.batchsvector3f_bufferoffset = 0;
11150 rsurface.batchtvector3f = NULL;
11151 rsurface.batchtvector3f_vertexbuffer = NULL;
11152 rsurface.batchtvector3f_bufferoffset = 0;
11153 rsurface.batchnormal3f = NULL;
11154 rsurface.batchnormal3f_vertexbuffer = NULL;
11155 rsurface.batchnormal3f_bufferoffset = 0;
11156 rsurface.batchlightmapcolor4f = NULL;
11157 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11158 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11159 rsurface.batchtexcoordtexture2f = NULL;
11160 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11161 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11162 rsurface.batchtexcoordlightmap2f = NULL;
11163 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11164 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11165 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11166 rsurface.batchelement3i_indexbuffer = NULL;
11167 rsurface.batchelement3i_bufferoffset = 0;
11168 rsurface.batchelement3s = NULL;
11169 rsurface.batchelement3s_indexbuffer = NULL;
11170 rsurface.batchelement3s_bufferoffset = 0;
11171 // we'll only be setting up certain arrays as needed
11172 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11173 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
11174 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11175 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11176 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11177 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11178 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11180 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11181 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11183 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11184 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11185 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11186 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11187 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11188 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11191 for (i = 0;i < texturenumsurfaces;i++)
11193 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11194 surfacenumvertices = texturesurfacelist[i]->num_vertices;
11195 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11196 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11197 // copy only the data requested
11198 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11199 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11200 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11202 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11203 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11204 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11205 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11206 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11208 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11209 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11211 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11212 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11213 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11214 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11215 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11216 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11218 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11219 numvertices += surfacenumvertices;
11220 numtriangles += surfacenumtriangles;
11223 // generate a 16bit index array as well if possible
11224 // (in general, dynamic batches fit)
11225 if (numvertices <= 65536)
11227 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11228 for (i = 0;i < numtriangles*3;i++)
11229 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11232 // since we've copied everything, the batch now starts at 0
11233 rsurface.batchfirstvertex = 0;
11234 rsurface.batchnumvertices = batchnumvertices;
11235 rsurface.batchfirsttriangle = 0;
11236 rsurface.batchnumtriangles = batchnumtriangles;
11239 // q1bsp surfaces rendered in vertex color mode have to have colors
11240 // calculated based on lightstyles
11241 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11243 // generate color arrays for the surfaces in this list
11247 const int *offsets;
11248 const unsigned char *lm;
11249 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11250 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11251 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11253 for (i = 0;i < texturenumsurfaces;i++)
11255 surface = texturesurfacelist[i];
11256 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11257 surfacenumvertices = surface->num_vertices;
11258 if (surface->lightmapinfo->samples)
11260 for (j = 0;j < surfacenumvertices;j++)
11262 lm = surface->lightmapinfo->samples + offsets[j];
11263 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11264 VectorScale(lm, scale, c);
11265 if (surface->lightmapinfo->styles[1] != 255)
11267 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11269 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11270 VectorMA(c, scale, lm, c);
11271 if (surface->lightmapinfo->styles[2] != 255)
11274 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11275 VectorMA(c, scale, lm, c);
11276 if (surface->lightmapinfo->styles[3] != 255)
11279 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11280 VectorMA(c, scale, lm, c);
11287 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);
11293 for (j = 0;j < surfacenumvertices;j++)
11295 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11302 // if vertices are deformed (sprite flares and things in maps, possibly
11303 // water waves, bulges and other deformations), modify the copied vertices
11305 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11307 switch (deform->deform)
11310 case Q3DEFORM_PROJECTIONSHADOW:
11311 case Q3DEFORM_TEXT0:
11312 case Q3DEFORM_TEXT1:
11313 case Q3DEFORM_TEXT2:
11314 case Q3DEFORM_TEXT3:
11315 case Q3DEFORM_TEXT4:
11316 case Q3DEFORM_TEXT5:
11317 case Q3DEFORM_TEXT6:
11318 case Q3DEFORM_TEXT7:
11319 case Q3DEFORM_NONE:
11321 case Q3DEFORM_AUTOSPRITE:
11322 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11323 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11324 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11325 VectorNormalize(newforward);
11326 VectorNormalize(newright);
11327 VectorNormalize(newup);
11328 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11329 // rsurface.batchvertex3f_vertexbuffer = NULL;
11330 // rsurface.batchvertex3f_bufferoffset = 0;
11331 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
11332 // rsurface.batchsvector3f_vertexbuffer = NULL;
11333 // rsurface.batchsvector3f_bufferoffset = 0;
11334 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
11335 // rsurface.batchtvector3f_vertexbuffer = NULL;
11336 // rsurface.batchtvector3f_bufferoffset = 0;
11337 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11338 // rsurface.batchnormal3f_vertexbuffer = NULL;
11339 // rsurface.batchnormal3f_bufferoffset = 0;
11340 // a single autosprite surface can contain multiple sprites...
11341 for (j = 0;j < batchnumvertices - 3;j += 4)
11343 VectorClear(center);
11344 for (i = 0;i < 4;i++)
11345 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11346 VectorScale(center, 0.25f, center);
11347 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11348 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11349 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11350 for (i = 0;i < 4;i++)
11352 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11353 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
11356 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11357 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11358 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);
11360 case Q3DEFORM_AUTOSPRITE2:
11361 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11362 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11363 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11364 VectorNormalize(newforward);
11365 VectorNormalize(newright);
11366 VectorNormalize(newup);
11367 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11368 // rsurface.batchvertex3f_vertexbuffer = NULL;
11369 // rsurface.batchvertex3f_bufferoffset = 0;
11371 const float *v1, *v2;
11381 memset(shortest, 0, sizeof(shortest));
11382 // a single autosprite surface can contain multiple sprites...
11383 for (j = 0;j < batchnumvertices - 3;j += 4)
11385 VectorClear(center);
11386 for (i = 0;i < 4;i++)
11387 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11388 VectorScale(center, 0.25f, center);
11389 // find the two shortest edges, then use them to define the
11390 // axis vectors for rotating around the central axis
11391 for (i = 0;i < 6;i++)
11393 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11394 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11395 l = VectorDistance2(v1, v2);
11396 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11397 if (v1[2] != v2[2])
11398 l += (1.0f / 1024.0f);
11399 if (shortest[0].length2 > l || i == 0)
11401 shortest[1] = shortest[0];
11402 shortest[0].length2 = l;
11403 shortest[0].v1 = v1;
11404 shortest[0].v2 = v2;
11406 else if (shortest[1].length2 > l || i == 1)
11408 shortest[1].length2 = l;
11409 shortest[1].v1 = v1;
11410 shortest[1].v2 = v2;
11413 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11414 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11415 // this calculates the right vector from the shortest edge
11416 // and the up vector from the edge midpoints
11417 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11418 VectorNormalize(right);
11419 VectorSubtract(end, start, up);
11420 VectorNormalize(up);
11421 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11422 VectorSubtract(rsurface.localvieworigin, center, forward);
11423 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11424 VectorNegate(forward, forward);
11425 VectorReflect(forward, 0, up, forward);
11426 VectorNormalize(forward);
11427 CrossProduct(up, forward, newright);
11428 VectorNormalize(newright);
11429 // rotate the quad around the up axis vector, this is made
11430 // especially easy by the fact we know the quad is flat,
11431 // so we only have to subtract the center position and
11432 // measure distance along the right vector, and then
11433 // multiply that by the newright vector and add back the
11435 // we also need to subtract the old position to undo the
11436 // displacement from the center, which we do with a
11437 // DotProduct, the subtraction/addition of center is also
11438 // optimized into DotProducts here
11439 l = DotProduct(right, center);
11440 for (i = 0;i < 4;i++)
11442 v1 = rsurface.batchvertex3f + 3*(j+i);
11443 f = DotProduct(right, v1) - l;
11444 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
11448 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11450 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11451 // rsurface.batchnormal3f_vertexbuffer = NULL;
11452 // rsurface.batchnormal3f_bufferoffset = 0;
11453 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11455 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11457 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11458 // rsurface.batchsvector3f_vertexbuffer = NULL;
11459 // rsurface.batchsvector3f_bufferoffset = 0;
11460 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11461 // rsurface.batchtvector3f_vertexbuffer = NULL;
11462 // rsurface.batchtvector3f_bufferoffset = 0;
11463 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);
11466 case Q3DEFORM_NORMAL:
11467 // deform the normals to make reflections wavey
11468 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11469 rsurface.batchnormal3f_vertexbuffer = NULL;
11470 rsurface.batchnormal3f_bufferoffset = 0;
11471 for (j = 0;j < batchnumvertices;j++)
11474 float *normal = rsurface.batchnormal3f + 3*j;
11475 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11476 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11477 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]);
11478 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]);
11479 VectorNormalize(normal);
11481 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11483 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11484 // rsurface.batchsvector3f_vertexbuffer = NULL;
11485 // rsurface.batchsvector3f_bufferoffset = 0;
11486 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11487 // rsurface.batchtvector3f_vertexbuffer = NULL;
11488 // rsurface.batchtvector3f_bufferoffset = 0;
11489 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);
11492 case Q3DEFORM_WAVE:
11493 // deform vertex array to make wavey water and flags and such
11494 waveparms[0] = deform->waveparms[0];
11495 waveparms[1] = deform->waveparms[1];
11496 waveparms[2] = deform->waveparms[2];
11497 waveparms[3] = deform->waveparms[3];
11498 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11499 break; // if wavefunc is a nop, don't make a dynamic vertex array
11500 // this is how a divisor of vertex influence on deformation
11501 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11502 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11503 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11504 // rsurface.batchvertex3f_vertexbuffer = NULL;
11505 // rsurface.batchvertex3f_bufferoffset = 0;
11506 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11507 // rsurface.batchnormal3f_vertexbuffer = NULL;
11508 // rsurface.batchnormal3f_bufferoffset = 0;
11509 for (j = 0;j < batchnumvertices;j++)
11511 // if the wavefunc depends on time, evaluate it per-vertex
11514 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11515 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11517 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
11519 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11520 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11521 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11523 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11524 // rsurface.batchsvector3f_vertexbuffer = NULL;
11525 // rsurface.batchsvector3f_bufferoffset = 0;
11526 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11527 // rsurface.batchtvector3f_vertexbuffer = NULL;
11528 // rsurface.batchtvector3f_bufferoffset = 0;
11529 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);
11532 case Q3DEFORM_BULGE:
11533 // deform vertex array to make the surface have moving bulges
11534 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11535 // rsurface.batchvertex3f_vertexbuffer = NULL;
11536 // rsurface.batchvertex3f_bufferoffset = 0;
11537 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11538 // rsurface.batchnormal3f_vertexbuffer = NULL;
11539 // rsurface.batchnormal3f_bufferoffset = 0;
11540 for (j = 0;j < batchnumvertices;j++)
11542 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
11543 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
11545 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11546 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11547 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11549 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11550 // rsurface.batchsvector3f_vertexbuffer = NULL;
11551 // rsurface.batchsvector3f_bufferoffset = 0;
11552 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11553 // rsurface.batchtvector3f_vertexbuffer = NULL;
11554 // rsurface.batchtvector3f_bufferoffset = 0;
11555 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);
11558 case Q3DEFORM_MOVE:
11559 // deform vertex array
11560 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11561 break; // if wavefunc is a nop, don't make a dynamic vertex array
11562 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
11563 VectorScale(deform->parms, scale, waveparms);
11564 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11565 // rsurface.batchvertex3f_vertexbuffer = NULL;
11566 // rsurface.batchvertex3f_bufferoffset = 0;
11567 for (j = 0;j < batchnumvertices;j++)
11568 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
11573 // generate texcoords based on the chosen texcoord source
11574 switch(rsurface.texture->tcgen.tcgen)
11577 case Q3TCGEN_TEXTURE:
11579 case Q3TCGEN_LIGHTMAP:
11580 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11581 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11582 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11583 if (rsurface.batchtexcoordlightmap2f)
11584 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
11586 case Q3TCGEN_VECTOR:
11587 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11588 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11589 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11590 for (j = 0;j < batchnumvertices;j++)
11592 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
11593 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
11596 case Q3TCGEN_ENVIRONMENT:
11597 // make environment reflections using a spheremap
11598 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11599 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11600 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11601 for (j = 0;j < batchnumvertices;j++)
11603 // identical to Q3A's method, but executed in worldspace so
11604 // carried models can be shiny too
11606 float viewer[3], d, reflected[3], worldreflected[3];
11608 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
11609 // VectorNormalize(viewer);
11611 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
11613 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
11614 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
11615 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
11616 // note: this is proportinal to viewer, so we can normalize later
11618 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
11619 VectorNormalize(worldreflected);
11621 // note: this sphere map only uses world x and z!
11622 // so positive and negative y will LOOK THE SAME.
11623 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
11624 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
11628 // the only tcmod that needs software vertex processing is turbulent, so
11629 // check for it here and apply the changes if needed
11630 // and we only support that as the first one
11631 // (handling a mixture of turbulent and other tcmods would be problematic
11632 // without punting it entirely to a software path)
11633 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11635 amplitude = rsurface.texture->tcmods[0].parms[1];
11636 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
11637 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11638 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11639 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11640 for (j = 0;j < batchnumvertices;j++)
11642 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);
11643 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
11647 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11649 // convert the modified arrays to vertex structs
11650 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
11651 // rsurface.batchvertexmeshbuffer = NULL;
11652 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
11653 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11654 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
11655 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
11656 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11657 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
11658 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
11660 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11662 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
11663 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
11666 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
11667 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11668 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
11669 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
11670 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11671 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
11672 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
11673 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11674 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
11678 void RSurf_DrawBatch(void)
11680 // sometimes a zero triangle surface (usually a degenerate patch) makes it
11681 // through the pipeline, killing it earlier in the pipeline would have
11682 // per-surface overhead rather than per-batch overhead, so it's best to
11683 // reject it here, before it hits glDraw.
11684 if (rsurface.batchnumtriangles == 0)
11687 // batch debugging code
11688 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
11694 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
11695 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
11698 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
11700 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
11702 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
11703 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);
11710 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);
11713 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
11715 // pick the closest matching water plane
11716 int planeindex, vertexindex, bestplaneindex = -1;
11720 r_waterstate_waterplane_t *p;
11721 qboolean prepared = false;
11723 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
11725 if(p->camera_entity != rsurface.texture->camera_entity)
11730 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11732 if(rsurface.batchnumvertices == 0)
11735 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
11737 Matrix4x4_Transform(&rsurface.matrix, v, vert);
11738 d += fabs(PlaneDiff(vert, &p->plane));
11740 if (bestd > d || bestplaneindex < 0)
11743 bestplaneindex = planeindex;
11746 return bestplaneindex;
11747 // NOTE: this MAY return a totally unrelated water plane; we can ignore
11748 // this situation though, as it might be better to render single larger
11749 // batches with useless stuff (backface culled for example) than to
11750 // render multiple smaller batches
11753 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
11756 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11757 rsurface.passcolor4f_vertexbuffer = 0;
11758 rsurface.passcolor4f_bufferoffset = 0;
11759 for (i = 0;i < rsurface.batchnumvertices;i++)
11760 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
11763 static void RSurf_DrawBatch_GL11_ApplyFog(void)
11770 if (rsurface.passcolor4f)
11772 // generate color arrays
11773 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11774 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11775 rsurface.passcolor4f_vertexbuffer = 0;
11776 rsurface.passcolor4f_bufferoffset = 0;
11777 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)
11779 f = RSurf_FogVertex(v);
11788 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11789 rsurface.passcolor4f_vertexbuffer = 0;
11790 rsurface.passcolor4f_bufferoffset = 0;
11791 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
11793 f = RSurf_FogVertex(v);
11802 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
11809 if (!rsurface.passcolor4f)
11811 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11812 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11813 rsurface.passcolor4f_vertexbuffer = 0;
11814 rsurface.passcolor4f_bufferoffset = 0;
11815 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)
11817 f = RSurf_FogVertex(v);
11818 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
11819 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
11820 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
11825 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
11830 if (!rsurface.passcolor4f)
11832 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11833 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11834 rsurface.passcolor4f_vertexbuffer = 0;
11835 rsurface.passcolor4f_bufferoffset = 0;
11836 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11845 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
11850 if (!rsurface.passcolor4f)
11852 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11853 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11854 rsurface.passcolor4f_vertexbuffer = 0;
11855 rsurface.passcolor4f_bufferoffset = 0;
11856 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11858 c2[0] = c[0] + r_refdef.scene.ambient;
11859 c2[1] = c[1] + r_refdef.scene.ambient;
11860 c2[2] = c[2] + r_refdef.scene.ambient;
11865 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11868 rsurface.passcolor4f = NULL;
11869 rsurface.passcolor4f_vertexbuffer = 0;
11870 rsurface.passcolor4f_bufferoffset = 0;
11871 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
11872 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11873 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11874 GL_Color(r, g, b, a);
11875 R_Mesh_TexBind(0, rsurface.lightmaptexture);
11879 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11881 // TODO: optimize applyfog && applycolor case
11882 // just apply fog if necessary, and tint the fog color array if necessary
11883 rsurface.passcolor4f = NULL;
11884 rsurface.passcolor4f_vertexbuffer = 0;
11885 rsurface.passcolor4f_bufferoffset = 0;
11886 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
11887 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11888 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11889 GL_Color(r, g, b, a);
11893 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11896 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11897 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11898 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11899 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
11900 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11901 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11902 GL_Color(r, g, b, a);
11906 static void RSurf_DrawBatch_GL11_ClampColor(void)
11911 if (!rsurface.passcolor4f)
11913 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
11915 c2[0] = bound(0.0f, c1[0], 1.0f);
11916 c2[1] = bound(0.0f, c1[1], 1.0f);
11917 c2[2] = bound(0.0f, c1[2], 1.0f);
11918 c2[3] = bound(0.0f, c1[3], 1.0f);
11922 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
11932 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11933 rsurface.passcolor4f_vertexbuffer = 0;
11934 rsurface.passcolor4f_bufferoffset = 0;
11935 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)
11937 f = -DotProduct(r_refdef.view.forward, n);
11939 f = f * 0.85 + 0.15; // work around so stuff won't get black
11940 f *= r_refdef.lightmapintensity;
11941 Vector4Set(c, f, f, f, 1);
11945 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11947 RSurf_DrawBatch_GL11_ApplyFakeLight();
11948 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
11949 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11950 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11951 GL_Color(r, g, b, a);
11955 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
11963 vec3_t ambientcolor;
11964 vec3_t diffusecolor;
11968 VectorCopy(rsurface.modellight_lightdir, lightdir);
11969 f = 0.5f * r_refdef.lightmapintensity;
11970 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
11971 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
11972 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
11973 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
11974 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
11975 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
11977 if (VectorLength2(diffusecolor) > 0)
11979 // q3-style directional shading
11980 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11981 rsurface.passcolor4f_vertexbuffer = 0;
11982 rsurface.passcolor4f_bufferoffset = 0;
11983 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)
11985 if ((f = DotProduct(n, lightdir)) > 0)
11986 VectorMA(ambientcolor, f, diffusecolor, c);
11988 VectorCopy(ambientcolor, c);
11995 *applycolor = false;
11999 *r = ambientcolor[0];
12000 *g = ambientcolor[1];
12001 *b = ambientcolor[2];
12002 rsurface.passcolor4f = NULL;
12003 rsurface.passcolor4f_vertexbuffer = 0;
12004 rsurface.passcolor4f_bufferoffset = 0;
12008 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12010 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12011 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12012 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12013 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12014 GL_Color(r, g, b, a);
12018 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12024 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12026 f = 1 - RSurf_FogVertex(v);
12034 void RSurf_SetupDepthAndCulling(void)
12036 // submodels are biased to avoid z-fighting with world surfaces that they
12037 // may be exactly overlapping (avoids z-fighting artifacts on certain
12038 // doors and things in Quake maps)
12039 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12040 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12041 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12042 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12045 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12047 // transparent sky would be ridiculous
12048 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12050 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12051 skyrenderlater = true;
12052 RSurf_SetupDepthAndCulling();
12053 GL_DepthMask(true);
12054 // LordHavoc: HalfLife maps have freaky skypolys so don't use
12055 // skymasking on them, and Quake3 never did sky masking (unlike
12056 // software Quake and software Quake2), so disable the sky masking
12057 // in Quake3 maps as it causes problems with q3map2 sky tricks,
12058 // and skymasking also looks very bad when noclipping outside the
12059 // level, so don't use it then either.
12060 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12062 R_Mesh_ResetTextureState();
12063 if (skyrendermasked)
12065 R_SetupShader_DepthOrShadow();
12066 // depth-only (masking)
12067 GL_ColorMask(0,0,0,0);
12068 // just to make sure that braindead drivers don't draw
12069 // anything despite that colormask...
12070 GL_BlendFunc(GL_ZERO, GL_ONE);
12071 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12072 if (rsurface.batchvertex3fbuffer)
12073 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12075 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12079 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12081 GL_BlendFunc(GL_ONE, GL_ZERO);
12082 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12083 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12084 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12087 if (skyrendermasked)
12088 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12090 R_Mesh_ResetTextureState();
12091 GL_Color(1, 1, 1, 1);
12094 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12095 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12096 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12098 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12102 // render screenspace normalmap to texture
12103 GL_DepthMask(true);
12104 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12109 // bind lightmap texture
12111 // water/refraction/reflection/camera surfaces have to be handled specially
12112 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
12114 int start, end, startplaneindex;
12115 for (start = 0;start < texturenumsurfaces;start = end)
12117 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12118 if(startplaneindex < 0)
12120 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
12121 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
12125 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12127 // now that we have a batch using the same planeindex, render it
12128 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
12130 // render water or distortion background
12131 GL_DepthMask(true);
12132 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));
12134 // blend surface on top
12135 GL_DepthMask(false);
12136 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12139 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
12141 // render surface with reflection texture as input
12142 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12143 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));
12150 // render surface batch normally
12151 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12152 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12156 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12158 // OpenGL 1.3 path - anything not completely ancient
12159 qboolean applycolor;
12162 const texturelayer_t *layer;
12163 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);
12164 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12166 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12169 int layertexrgbscale;
12170 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12172 if (layerindex == 0)
12173 GL_AlphaTest(true);
12176 GL_AlphaTest(false);
12177 GL_DepthFunc(GL_EQUAL);
12180 GL_DepthMask(layer->depthmask && writedepth);
12181 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12182 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12184 layertexrgbscale = 4;
12185 VectorScale(layer->color, 0.25f, layercolor);
12187 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12189 layertexrgbscale = 2;
12190 VectorScale(layer->color, 0.5f, layercolor);
12194 layertexrgbscale = 1;
12195 VectorScale(layer->color, 1.0f, layercolor);
12197 layercolor[3] = layer->color[3];
12198 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12199 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12200 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12201 switch (layer->type)
12203 case TEXTURELAYERTYPE_LITTEXTURE:
12204 // single-pass lightmapped texture with 2x rgbscale
12205 R_Mesh_TexBind(0, r_texture_white);
12206 R_Mesh_TexMatrix(0, NULL);
12207 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12208 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12209 R_Mesh_TexBind(1, layer->texture);
12210 R_Mesh_TexMatrix(1, &layer->texmatrix);
12211 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12212 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12213 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12214 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12215 else if (FAKELIGHT_ENABLED)
12216 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12217 else if (rsurface.uselightmaptexture)
12218 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12220 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12222 case TEXTURELAYERTYPE_TEXTURE:
12223 // singletexture unlit texture with transparency support
12224 R_Mesh_TexBind(0, layer->texture);
12225 R_Mesh_TexMatrix(0, &layer->texmatrix);
12226 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12227 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12228 R_Mesh_TexBind(1, 0);
12229 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12230 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12232 case TEXTURELAYERTYPE_FOG:
12233 // singletexture fogging
12234 if (layer->texture)
12236 R_Mesh_TexBind(0, layer->texture);
12237 R_Mesh_TexMatrix(0, &layer->texmatrix);
12238 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12239 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12243 R_Mesh_TexBind(0, 0);
12244 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12246 R_Mesh_TexBind(1, 0);
12247 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12248 // generate a color array for the fog pass
12249 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12250 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12254 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12257 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12259 GL_DepthFunc(GL_LEQUAL);
12260 GL_AlphaTest(false);
12264 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12266 // OpenGL 1.1 - crusty old voodoo path
12269 const texturelayer_t *layer;
12270 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);
12271 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12273 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12275 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12277 if (layerindex == 0)
12278 GL_AlphaTest(true);
12281 GL_AlphaTest(false);
12282 GL_DepthFunc(GL_EQUAL);
12285 GL_DepthMask(layer->depthmask && writedepth);
12286 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12287 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12288 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12289 switch (layer->type)
12291 case TEXTURELAYERTYPE_LITTEXTURE:
12292 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12294 // two-pass lit texture with 2x rgbscale
12295 // first the lightmap pass
12296 R_Mesh_TexBind(0, r_texture_white);
12297 R_Mesh_TexMatrix(0, NULL);
12298 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12299 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12300 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12301 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12302 else if (FAKELIGHT_ENABLED)
12303 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12304 else if (rsurface.uselightmaptexture)
12305 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12307 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12308 // then apply the texture to it
12309 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12310 R_Mesh_TexBind(0, layer->texture);
12311 R_Mesh_TexMatrix(0, &layer->texmatrix);
12312 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12313 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12314 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);
12318 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12319 R_Mesh_TexBind(0, layer->texture);
12320 R_Mesh_TexMatrix(0, &layer->texmatrix);
12321 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12322 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12323 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12324 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);
12326 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);
12329 case TEXTURELAYERTYPE_TEXTURE:
12330 // singletexture unlit texture with transparency support
12331 R_Mesh_TexBind(0, layer->texture);
12332 R_Mesh_TexMatrix(0, &layer->texmatrix);
12333 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12334 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12335 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);
12337 case TEXTURELAYERTYPE_FOG:
12338 // singletexture fogging
12339 if (layer->texture)
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);
12348 R_Mesh_TexBind(0, 0);
12349 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12351 // generate a color array for the fog pass
12352 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12353 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12357 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12360 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12362 GL_DepthFunc(GL_LEQUAL);
12363 GL_AlphaTest(false);
12367 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12371 r_vertexgeneric_t *batchvertex;
12374 // R_Mesh_ResetTextureState();
12375 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12377 if(rsurface.texture && rsurface.texture->currentskinframe)
12379 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12380 c[3] *= rsurface.texture->currentalpha;
12390 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12392 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12393 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12394 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12397 // brighten it up (as texture value 127 means "unlit")
12398 c[0] *= 2 * r_refdef.view.colorscale;
12399 c[1] *= 2 * r_refdef.view.colorscale;
12400 c[2] *= 2 * r_refdef.view.colorscale;
12402 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12403 c[3] *= r_wateralpha.value;
12405 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12407 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12408 GL_DepthMask(false);
12410 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12412 GL_BlendFunc(GL_ONE, GL_ONE);
12413 GL_DepthMask(false);
12415 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12417 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12418 GL_DepthMask(false);
12420 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12422 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12423 GL_DepthMask(false);
12427 GL_BlendFunc(GL_ONE, GL_ZERO);
12428 GL_DepthMask(writedepth);
12431 if (r_showsurfaces.integer == 3)
12433 rsurface.passcolor4f = NULL;
12435 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12437 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12439 rsurface.passcolor4f = NULL;
12440 rsurface.passcolor4f_vertexbuffer = 0;
12441 rsurface.passcolor4f_bufferoffset = 0;
12443 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12445 qboolean applycolor = true;
12448 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12450 r_refdef.lightmapintensity = 1;
12451 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12452 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12454 else if (FAKELIGHT_ENABLED)
12456 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12458 r_refdef.lightmapintensity = r_fakelight_intensity.value;
12459 RSurf_DrawBatch_GL11_ApplyFakeLight();
12460 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12464 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12466 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12467 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12468 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12471 if(!rsurface.passcolor4f)
12472 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12474 RSurf_DrawBatch_GL11_ApplyAmbient();
12475 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12476 if(r_refdef.fogenabled)
12477 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12478 RSurf_DrawBatch_GL11_ClampColor();
12480 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12481 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12484 else if (!r_refdef.view.showdebug)
12486 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12487 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12488 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12490 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12491 Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12493 R_Mesh_PrepareVertices_Generic_Unlock();
12496 else if (r_showsurfaces.integer == 4)
12498 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12499 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12500 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12502 unsigned char c = vi << 3;
12503 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12504 Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12506 R_Mesh_PrepareVertices_Generic_Unlock();
12509 else if (r_showsurfaces.integer == 2)
12512 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12513 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12514 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12516 unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12517 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12518 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12519 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12520 Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12521 Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12522 Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12524 R_Mesh_PrepareVertices_Generic_Unlock();
12525 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12529 int texturesurfaceindex;
12531 const msurface_t *surface;
12532 unsigned char surfacecolor4ub[4];
12533 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12534 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12536 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12538 surface = texturesurfacelist[texturesurfaceindex];
12539 k = (int)(((size_t)surface) / sizeof(msurface_t));
12540 Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
12541 for (j = 0;j < surface->num_vertices;j++)
12543 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12544 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
12548 R_Mesh_PrepareVertices_Generic_Unlock();
12553 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12556 RSurf_SetupDepthAndCulling();
12557 if (r_showsurfaces.integer)
12559 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12562 switch (vid.renderpath)
12564 case RENDERPATH_GL20:
12565 case RENDERPATH_D3D9:
12566 case RENDERPATH_D3D10:
12567 case RENDERPATH_D3D11:
12568 case RENDERPATH_SOFT:
12569 case RENDERPATH_GLES2:
12570 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12572 case RENDERPATH_GL13:
12573 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12575 case RENDERPATH_GL11:
12576 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12582 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12585 RSurf_SetupDepthAndCulling();
12586 if (r_showsurfaces.integer)
12588 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12591 switch (vid.renderpath)
12593 case RENDERPATH_GL20:
12594 case RENDERPATH_D3D9:
12595 case RENDERPATH_D3D10:
12596 case RENDERPATH_D3D11:
12597 case RENDERPATH_SOFT:
12598 case RENDERPATH_GLES2:
12599 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12601 case RENDERPATH_GL13:
12602 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12604 case RENDERPATH_GL11:
12605 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12611 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12614 int texturenumsurfaces, endsurface;
12615 texture_t *texture;
12616 const msurface_t *surface;
12617 #define MAXBATCH_TRANSPARENTSURFACES 256
12618 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
12620 // if the model is static it doesn't matter what value we give for
12621 // wantnormals and wanttangents, so this logic uses only rules applicable
12622 // to a model, knowing that they are meaningless otherwise
12623 if (ent == r_refdef.scene.worldentity)
12624 RSurf_ActiveWorldEntity();
12625 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12626 RSurf_ActiveModelEntity(ent, false, false, false);
12629 switch (vid.renderpath)
12631 case RENDERPATH_GL20:
12632 case RENDERPATH_D3D9:
12633 case RENDERPATH_D3D10:
12634 case RENDERPATH_D3D11:
12635 case RENDERPATH_SOFT:
12636 case RENDERPATH_GLES2:
12637 RSurf_ActiveModelEntity(ent, true, true, false);
12639 case RENDERPATH_GL13:
12640 case RENDERPATH_GL11:
12641 RSurf_ActiveModelEntity(ent, true, false, false);
12646 if (r_transparentdepthmasking.integer)
12648 qboolean setup = false;
12649 for (i = 0;i < numsurfaces;i = j)
12652 surface = rsurface.modelsurfaces + surfacelist[i];
12653 texture = surface->texture;
12654 rsurface.texture = R_GetCurrentTexture(texture);
12655 rsurface.lightmaptexture = NULL;
12656 rsurface.deluxemaptexture = NULL;
12657 rsurface.uselightmaptexture = false;
12658 // scan ahead until we find a different texture
12659 endsurface = min(i + 1024, numsurfaces);
12660 texturenumsurfaces = 0;
12661 texturesurfacelist[texturenumsurfaces++] = surface;
12662 for (;j < endsurface;j++)
12664 surface = rsurface.modelsurfaces + surfacelist[j];
12665 if (texture != surface->texture)
12667 texturesurfacelist[texturenumsurfaces++] = surface;
12669 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
12671 // render the range of surfaces as depth
12675 GL_ColorMask(0,0,0,0);
12677 GL_DepthTest(true);
12678 GL_BlendFunc(GL_ONE, GL_ZERO);
12679 GL_DepthMask(true);
12680 // R_Mesh_ResetTextureState();
12681 R_SetupShader_DepthOrShadow();
12683 RSurf_SetupDepthAndCulling();
12684 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
12685 if (rsurface.batchvertex3fbuffer)
12686 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12688 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12692 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12695 for (i = 0;i < numsurfaces;i = j)
12698 surface = rsurface.modelsurfaces + surfacelist[i];
12699 texture = surface->texture;
12700 rsurface.texture = R_GetCurrentTexture(texture);
12701 // scan ahead until we find a different texture
12702 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
12703 texturenumsurfaces = 0;
12704 texturesurfacelist[texturenumsurfaces++] = surface;
12705 if(FAKELIGHT_ENABLED)
12707 rsurface.lightmaptexture = NULL;
12708 rsurface.deluxemaptexture = NULL;
12709 rsurface.uselightmaptexture = false;
12710 for (;j < endsurface;j++)
12712 surface = rsurface.modelsurfaces + surfacelist[j];
12713 if (texture != surface->texture)
12715 texturesurfacelist[texturenumsurfaces++] = surface;
12720 rsurface.lightmaptexture = surface->lightmaptexture;
12721 rsurface.deluxemaptexture = surface->deluxemaptexture;
12722 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
12723 for (;j < endsurface;j++)
12725 surface = rsurface.modelsurfaces + surfacelist[j];
12726 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
12728 texturesurfacelist[texturenumsurfaces++] = surface;
12731 // render the range of surfaces
12732 if (ent == r_refdef.scene.worldentity)
12733 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12735 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12737 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12740 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
12742 // transparent surfaces get pushed off into the transparent queue
12743 int surfacelistindex;
12744 const msurface_t *surface;
12745 vec3_t tempcenter, center;
12746 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
12748 surface = texturesurfacelist[surfacelistindex];
12749 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
12750 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
12751 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
12752 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
12753 if (queueentity->transparent_offset) // transparent offset
12755 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
12756 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
12757 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
12759 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
12763 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12765 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
12767 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
12769 RSurf_SetupDepthAndCulling();
12770 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
12771 if (rsurface.batchvertex3fbuffer)
12772 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12774 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12778 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
12780 const entity_render_t *queueentity = r_refdef.scene.worldentity;
12783 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12786 if (!rsurface.texture->currentnumlayers)
12788 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12789 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12791 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12793 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12794 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12795 else if (!rsurface.texture->currentnumlayers)
12797 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12799 // in the deferred case, transparent surfaces were queued during prepass
12800 if (!r_shadow_usingdeferredprepass)
12801 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12805 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12806 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12811 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12814 texture_t *texture;
12815 R_FrameData_SetMark();
12816 // break the surface list down into batches by texture and use of lightmapping
12817 for (i = 0;i < numsurfaces;i = j)
12820 // texture is the base texture pointer, rsurface.texture is the
12821 // current frame/skin the texture is directing us to use (for example
12822 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12823 // use skin 1 instead)
12824 texture = surfacelist[i]->texture;
12825 rsurface.texture = R_GetCurrentTexture(texture);
12826 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12828 // if this texture is not the kind we want, skip ahead to the next one
12829 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12833 if(FAKELIGHT_ENABLED || depthonly || prepass)
12835 rsurface.lightmaptexture = NULL;
12836 rsurface.deluxemaptexture = NULL;
12837 rsurface.uselightmaptexture = false;
12838 // simply scan ahead until we find a different texture or lightmap state
12839 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12844 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12845 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12846 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
12847 // simply scan ahead until we find a different texture or lightmap state
12848 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12851 // render the range of surfaces
12852 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
12854 R_FrameData_ReturnToMark();
12857 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
12861 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12864 if (!rsurface.texture->currentnumlayers)
12866 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12867 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12869 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12871 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12872 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12873 else if (!rsurface.texture->currentnumlayers)
12875 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12877 // in the deferred case, transparent surfaces were queued during prepass
12878 if (!r_shadow_usingdeferredprepass)
12879 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12883 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12884 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12889 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12892 texture_t *texture;
12893 R_FrameData_SetMark();
12894 // break the surface list down into batches by texture and use of lightmapping
12895 for (i = 0;i < numsurfaces;i = j)
12898 // texture is the base texture pointer, rsurface.texture is the
12899 // current frame/skin the texture is directing us to use (for example
12900 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12901 // use skin 1 instead)
12902 texture = surfacelist[i]->texture;
12903 rsurface.texture = R_GetCurrentTexture(texture);
12904 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12906 // if this texture is not the kind we want, skip ahead to the next one
12907 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12911 if(FAKELIGHT_ENABLED || depthonly || prepass)
12913 rsurface.lightmaptexture = NULL;
12914 rsurface.deluxemaptexture = NULL;
12915 rsurface.uselightmaptexture = false;
12916 // simply scan ahead until we find a different texture or lightmap state
12917 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12922 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12923 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12924 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
12925 // simply scan ahead until we find a different texture or lightmap state
12926 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12929 // render the range of surfaces
12930 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
12932 R_FrameData_ReturnToMark();
12935 float locboxvertex3f[6*4*3] =
12937 1,0,1, 1,0,0, 1,1,0, 1,1,1,
12938 0,1,1, 0,1,0, 0,0,0, 0,0,1,
12939 1,1,1, 1,1,0, 0,1,0, 0,1,1,
12940 0,0,1, 0,0,0, 1,0,0, 1,0,1,
12941 0,0,1, 1,0,1, 1,1,1, 0,1,1,
12942 1,0,0, 0,0,0, 0,1,0, 1,1,0
12945 unsigned short locboxelements[6*2*3] =
12950 12,13,14, 12,14,15,
12951 16,17,18, 16,18,19,
12955 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12958 cl_locnode_t *loc = (cl_locnode_t *)ent;
12960 float vertex3f[6*4*3];
12962 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12963 GL_DepthMask(false);
12964 GL_DepthRange(0, 1);
12965 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12966 GL_DepthTest(true);
12967 GL_CullFace(GL_NONE);
12968 R_EntityMatrix(&identitymatrix);
12970 // R_Mesh_ResetTextureState();
12972 i = surfacelist[0];
12973 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12974 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12975 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12976 surfacelist[0] < 0 ? 0.5f : 0.125f);
12978 if (VectorCompare(loc->mins, loc->maxs))
12980 VectorSet(size, 2, 2, 2);
12981 VectorMA(loc->mins, -0.5f, size, mins);
12985 VectorCopy(loc->mins, mins);
12986 VectorSubtract(loc->maxs, loc->mins, size);
12989 for (i = 0;i < 6*4*3;)
12990 for (j = 0;j < 3;j++, i++)
12991 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
12993 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
12994 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12995 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
12998 void R_DrawLocs(void)
13001 cl_locnode_t *loc, *nearestloc;
13003 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13004 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13006 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13007 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13011 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13013 if (decalsystem->decals)
13014 Mem_Free(decalsystem->decals);
13015 memset(decalsystem, 0, sizeof(*decalsystem));
13018 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)
13021 tridecal_t *decals;
13024 // expand or initialize the system
13025 if (decalsystem->maxdecals <= decalsystem->numdecals)
13027 decalsystem_t old = *decalsystem;
13028 qboolean useshortelements;
13029 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13030 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13031 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)));
13032 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13033 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13034 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13035 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13036 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13037 if (decalsystem->numdecals)
13038 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13040 Mem_Free(old.decals);
13041 for (i = 0;i < decalsystem->maxdecals*3;i++)
13042 decalsystem->element3i[i] = i;
13043 if (useshortelements)
13044 for (i = 0;i < decalsystem->maxdecals*3;i++)
13045 decalsystem->element3s[i] = i;
13048 // grab a decal and search for another free slot for the next one
13049 decals = decalsystem->decals;
13050 decal = decalsystem->decals + (i = decalsystem->freedecal++);
13051 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13053 decalsystem->freedecal = i;
13054 if (decalsystem->numdecals <= i)
13055 decalsystem->numdecals = i + 1;
13057 // initialize the decal
13059 decal->triangleindex = triangleindex;
13060 decal->surfaceindex = surfaceindex;
13061 decal->decalsequence = decalsequence;
13062 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13063 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13064 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13065 decal->color4ub[0][3] = 255;
13066 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13067 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13068 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13069 decal->color4ub[1][3] = 255;
13070 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13071 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13072 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13073 decal->color4ub[2][3] = 255;
13074 decal->vertex3f[0][0] = v0[0];
13075 decal->vertex3f[0][1] = v0[1];
13076 decal->vertex3f[0][2] = v0[2];
13077 decal->vertex3f[1][0] = v1[0];
13078 decal->vertex3f[1][1] = v1[1];
13079 decal->vertex3f[1][2] = v1[2];
13080 decal->vertex3f[2][0] = v2[0];
13081 decal->vertex3f[2][1] = v2[1];
13082 decal->vertex3f[2][2] = v2[2];
13083 decal->texcoord2f[0][0] = t0[0];
13084 decal->texcoord2f[0][1] = t0[1];
13085 decal->texcoord2f[1][0] = t1[0];
13086 decal->texcoord2f[1][1] = t1[1];
13087 decal->texcoord2f[2][0] = t2[0];
13088 decal->texcoord2f[2][1] = t2[1];
13091 extern cvar_t cl_decals_bias;
13092 extern cvar_t cl_decals_models;
13093 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13094 // baseparms, parms, temps
13095 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)
13100 const float *vertex3f;
13102 float points[2][9][3];
13109 e = rsurface.modelelement3i + 3*triangleindex;
13111 vertex3f = rsurface.modelvertex3f;
13113 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13115 index = 3*e[cornerindex];
13116 VectorCopy(vertex3f + index, v[cornerindex]);
13119 //TriangleNormal(v[0], v[1], v[2], normal);
13120 //if (DotProduct(normal, localnormal) < 0.0f)
13122 // clip by each of the box planes formed from the projection matrix
13123 // if anything survives, we emit the decal
13124 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]);
13127 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]);
13130 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]);
13133 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]);
13136 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]);
13139 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]);
13142 // some part of the triangle survived, so we have to accept it...
13145 // dynamic always uses the original triangle
13147 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13149 index = 3*e[cornerindex];
13150 VectorCopy(vertex3f + index, v[cornerindex]);
13153 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13155 // convert vertex positions to texcoords
13156 Matrix4x4_Transform(projection, v[cornerindex], temp);
13157 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13158 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13159 // calculate distance fade from the projection origin
13160 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13161 f = bound(0.0f, f, 1.0f);
13162 c[cornerindex][0] = r * f;
13163 c[cornerindex][1] = g * f;
13164 c[cornerindex][2] = b * f;
13165 c[cornerindex][3] = 1.0f;
13166 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13169 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);
13171 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13172 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);
13174 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)
13176 matrix4x4_t projection;
13177 decalsystem_t *decalsystem;
13180 const msurface_t *surface;
13181 const msurface_t *surfaces;
13182 const int *surfacelist;
13183 const texture_t *texture;
13185 int numsurfacelist;
13186 int surfacelistindex;
13189 float localorigin[3];
13190 float localnormal[3];
13191 float localmins[3];
13192 float localmaxs[3];
13195 float planes[6][4];
13198 int bih_triangles_count;
13199 int bih_triangles[256];
13200 int bih_surfaces[256];
13202 decalsystem = &ent->decalsystem;
13203 model = ent->model;
13204 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13206 R_DecalSystem_Reset(&ent->decalsystem);
13210 if (!model->brush.data_leafs && !cl_decals_models.integer)
13212 if (decalsystem->model)
13213 R_DecalSystem_Reset(decalsystem);
13217 if (decalsystem->model != model)
13218 R_DecalSystem_Reset(decalsystem);
13219 decalsystem->model = model;
13221 RSurf_ActiveModelEntity(ent, false, false, false);
13223 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13224 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13225 VectorNormalize(localnormal);
13226 localsize = worldsize*rsurface.inversematrixscale;
13227 localmins[0] = localorigin[0] - localsize;
13228 localmins[1] = localorigin[1] - localsize;
13229 localmins[2] = localorigin[2] - localsize;
13230 localmaxs[0] = localorigin[0] + localsize;
13231 localmaxs[1] = localorigin[1] + localsize;
13232 localmaxs[2] = localorigin[2] + localsize;
13234 //VectorCopy(localnormal, planes[4]);
13235 //VectorVectors(planes[4], planes[2], planes[0]);
13236 AnglesFromVectors(angles, localnormal, NULL, false);
13237 AngleVectors(angles, planes[0], planes[2], planes[4]);
13238 VectorNegate(planes[0], planes[1]);
13239 VectorNegate(planes[2], planes[3]);
13240 VectorNegate(planes[4], planes[5]);
13241 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13242 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13243 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13244 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13245 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13246 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13251 matrix4x4_t forwardprojection;
13252 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13253 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13258 float projectionvector[4][3];
13259 VectorScale(planes[0], ilocalsize, projectionvector[0]);
13260 VectorScale(planes[2], ilocalsize, projectionvector[1]);
13261 VectorScale(planes[4], ilocalsize, projectionvector[2]);
13262 projectionvector[0][0] = planes[0][0] * ilocalsize;
13263 projectionvector[0][1] = planes[1][0] * ilocalsize;
13264 projectionvector[0][2] = planes[2][0] * ilocalsize;
13265 projectionvector[1][0] = planes[0][1] * ilocalsize;
13266 projectionvector[1][1] = planes[1][1] * ilocalsize;
13267 projectionvector[1][2] = planes[2][1] * ilocalsize;
13268 projectionvector[2][0] = planes[0][2] * ilocalsize;
13269 projectionvector[2][1] = planes[1][2] * ilocalsize;
13270 projectionvector[2][2] = planes[2][2] * ilocalsize;
13271 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13272 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13273 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13274 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13278 dynamic = model->surfmesh.isanimated;
13279 numsurfacelist = model->nummodelsurfaces;
13280 surfacelist = model->sortedmodelsurfaces;
13281 surfaces = model->data_surfaces;
13284 bih_triangles_count = -1;
13287 if(model->render_bih.numleafs)
13288 bih = &model->render_bih;
13289 else if(model->collision_bih.numleafs)
13290 bih = &model->collision_bih;
13293 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13294 if(bih_triangles_count == 0)
13296 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13298 if(bih_triangles_count > 0)
13300 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13302 surfaceindex = bih_surfaces[triangleindex];
13303 surface = surfaces + surfaceindex;
13304 texture = surface->texture;
13305 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13307 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13309 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13314 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13316 surfaceindex = surfacelist[surfacelistindex];
13317 surface = surfaces + surfaceindex;
13318 // check cull box first because it rejects more than any other check
13319 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13321 // skip transparent surfaces
13322 texture = surface->texture;
13323 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13325 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13327 numtriangles = surface->num_triangles;
13328 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13329 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13334 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13335 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)
13337 int renderentityindex;
13338 float worldmins[3];
13339 float worldmaxs[3];
13340 entity_render_t *ent;
13342 if (!cl_decals_newsystem.integer)
13345 worldmins[0] = worldorigin[0] - worldsize;
13346 worldmins[1] = worldorigin[1] - worldsize;
13347 worldmins[2] = worldorigin[2] - worldsize;
13348 worldmaxs[0] = worldorigin[0] + worldsize;
13349 worldmaxs[1] = worldorigin[1] + worldsize;
13350 worldmaxs[2] = worldorigin[2] + worldsize;
13352 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13354 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13356 ent = r_refdef.scene.entities[renderentityindex];
13357 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13360 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13364 typedef struct r_decalsystem_splatqueue_s
13366 vec3_t worldorigin;
13367 vec3_t worldnormal;
13373 r_decalsystem_splatqueue_t;
13375 int r_decalsystem_numqueued = 0;
13376 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13378 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)
13380 r_decalsystem_splatqueue_t *queue;
13382 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13385 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13386 VectorCopy(worldorigin, queue->worldorigin);
13387 VectorCopy(worldnormal, queue->worldnormal);
13388 Vector4Set(queue->color, r, g, b, a);
13389 Vector4Set(queue->tcrange, s1, t1, s2, t2);
13390 queue->worldsize = worldsize;
13391 queue->decalsequence = cl.decalsequence++;
13394 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13397 r_decalsystem_splatqueue_t *queue;
13399 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13400 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);
13401 r_decalsystem_numqueued = 0;
13404 extern cvar_t cl_decals_max;
13405 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13408 decalsystem_t *decalsystem = &ent->decalsystem;
13415 if (!decalsystem->numdecals)
13418 if (r_showsurfaces.integer)
13421 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13423 R_DecalSystem_Reset(decalsystem);
13427 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13428 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13430 if (decalsystem->lastupdatetime)
13431 frametime = (cl.time - decalsystem->lastupdatetime);
13434 decalsystem->lastupdatetime = cl.time;
13435 decal = decalsystem->decals;
13436 numdecals = decalsystem->numdecals;
13438 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13440 if (decal->color4ub[0][3])
13442 decal->lived += frametime;
13443 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13445 memset(decal, 0, sizeof(*decal));
13446 if (decalsystem->freedecal > i)
13447 decalsystem->freedecal = i;
13451 decal = decalsystem->decals;
13452 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13455 // collapse the array by shuffling the tail decals into the gaps
13458 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13459 decalsystem->freedecal++;
13460 if (decalsystem->freedecal == numdecals)
13462 decal[decalsystem->freedecal] = decal[--numdecals];
13465 decalsystem->numdecals = numdecals;
13467 if (numdecals <= 0)
13469 // if there are no decals left, reset decalsystem
13470 R_DecalSystem_Reset(decalsystem);
13474 extern skinframe_t *decalskinframe;
13475 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13478 decalsystem_t *decalsystem = &ent->decalsystem;
13487 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13490 numdecals = decalsystem->numdecals;
13494 if (r_showsurfaces.integer)
13497 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13499 R_DecalSystem_Reset(decalsystem);
13503 // if the model is static it doesn't matter what value we give for
13504 // wantnormals and wanttangents, so this logic uses only rules applicable
13505 // to a model, knowing that they are meaningless otherwise
13506 if (ent == r_refdef.scene.worldentity)
13507 RSurf_ActiveWorldEntity();
13509 RSurf_ActiveModelEntity(ent, false, false, false);
13511 decalsystem->lastupdatetime = cl.time;
13512 decal = decalsystem->decals;
13514 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13516 // update vertex positions for animated models
13517 v3f = decalsystem->vertex3f;
13518 c4f = decalsystem->color4f;
13519 t2f = decalsystem->texcoord2f;
13520 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13522 if (!decal->color4ub[0][3])
13525 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13528 // update color values for fading decals
13529 if (decal->lived >= cl_decals_time.value)
13531 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13532 alpha *= (1.0f/255.0f);
13535 alpha = 1.0f/255.0f;
13537 c4f[ 0] = decal->color4ub[0][0] * alpha;
13538 c4f[ 1] = decal->color4ub[0][1] * alpha;
13539 c4f[ 2] = decal->color4ub[0][2] * alpha;
13541 c4f[ 4] = decal->color4ub[1][0] * alpha;
13542 c4f[ 5] = decal->color4ub[1][1] * alpha;
13543 c4f[ 6] = decal->color4ub[1][2] * alpha;
13545 c4f[ 8] = decal->color4ub[2][0] * alpha;
13546 c4f[ 9] = decal->color4ub[2][1] * alpha;
13547 c4f[10] = decal->color4ub[2][2] * alpha;
13550 t2f[0] = decal->texcoord2f[0][0];
13551 t2f[1] = decal->texcoord2f[0][1];
13552 t2f[2] = decal->texcoord2f[1][0];
13553 t2f[3] = decal->texcoord2f[1][1];
13554 t2f[4] = decal->texcoord2f[2][0];
13555 t2f[5] = decal->texcoord2f[2][1];
13557 // update vertex positions for animated models
13558 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13560 e = rsurface.modelelement3i + 3*decal->triangleindex;
13561 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
13562 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
13563 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
13567 VectorCopy(decal->vertex3f[0], v3f);
13568 VectorCopy(decal->vertex3f[1], v3f + 3);
13569 VectorCopy(decal->vertex3f[2], v3f + 6);
13572 if (r_refdef.fogenabled)
13574 alpha = RSurf_FogVertex(v3f);
13575 VectorScale(c4f, alpha, c4f);
13576 alpha = RSurf_FogVertex(v3f + 3);
13577 VectorScale(c4f + 4, alpha, c4f + 4);
13578 alpha = RSurf_FogVertex(v3f + 6);
13579 VectorScale(c4f + 8, alpha, c4f + 8);
13590 r_refdef.stats.drawndecals += numtris;
13592 // now render the decals all at once
13593 // (this assumes they all use one particle font texture!)
13594 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);
13595 // R_Mesh_ResetTextureState();
13596 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
13597 GL_DepthMask(false);
13598 GL_DepthRange(0, 1);
13599 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
13600 GL_DepthTest(true);
13601 GL_CullFace(GL_NONE);
13602 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
13603 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
13604 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
13608 static void R_DrawModelDecals(void)
13612 // fade faster when there are too many decals
13613 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13614 for (i = 0;i < r_refdef.scene.numentities;i++)
13615 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13617 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
13618 for (i = 0;i < r_refdef.scene.numentities;i++)
13619 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13620 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
13622 R_DecalSystem_ApplySplatEntitiesQueue();
13624 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13625 for (i = 0;i < r_refdef.scene.numentities;i++)
13626 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13628 r_refdef.stats.totaldecals += numdecals;
13630 if (r_showsurfaces.integer)
13633 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
13635 for (i = 0;i < r_refdef.scene.numentities;i++)
13637 if (!r_refdef.viewcache.entityvisible[i])
13639 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13640 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
13644 extern cvar_t mod_collision_bih;
13645 void R_DrawDebugModel(void)
13647 entity_render_t *ent = rsurface.entity;
13648 int i, j, k, l, flagsmask;
13649 const msurface_t *surface;
13650 dp_model_t *model = ent->model;
13653 switch(vid.renderpath)
13655 case RENDERPATH_GL11:
13656 case RENDERPATH_GL13:
13657 case RENDERPATH_GL20:
13659 case RENDERPATH_D3D9:
13660 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13662 case RENDERPATH_D3D10:
13663 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13665 case RENDERPATH_D3D11:
13666 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13668 case RENDERPATH_SOFT:
13669 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13671 case RENDERPATH_GLES2:
13672 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13676 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
13678 // R_Mesh_ResetTextureState();
13679 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13680 GL_DepthRange(0, 1);
13681 GL_DepthTest(!r_showdisabledepthtest.integer);
13682 GL_DepthMask(false);
13683 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13685 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
13689 qboolean cullbox = ent == r_refdef.scene.worldentity;
13690 const q3mbrush_t *brush;
13691 const bih_t *bih = &model->collision_bih;
13692 const bih_leaf_t *bihleaf;
13693 float vertex3f[3][3];
13694 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
13696 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
13698 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
13700 switch (bihleaf->type)
13703 brush = model->brush.data_brushes + bihleaf->itemindex;
13704 if (brush->colbrushf && brush->colbrushf->numtriangles)
13706 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);
13707 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
13708 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
13711 case BIH_COLLISIONTRIANGLE:
13712 triangleindex = bihleaf->itemindex;
13713 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
13714 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
13715 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
13716 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);
13717 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13718 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13720 case BIH_RENDERTRIANGLE:
13721 triangleindex = bihleaf->itemindex;
13722 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
13723 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
13724 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
13725 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);
13726 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13727 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13733 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13735 if (r_showtris.integer || (r_shownormals.value != 0))
13737 if (r_showdisabledepthtest.integer)
13739 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13740 GL_DepthMask(false);
13744 GL_BlendFunc(GL_ONE, GL_ZERO);
13745 GL_DepthMask(true);
13747 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
13749 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
13751 rsurface.texture = R_GetCurrentTexture(surface->texture);
13752 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
13754 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
13755 if (r_showtris.value > 0)
13757 if (!rsurface.texture->currentlayers->depthmask)
13758 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
13759 else if (ent == r_refdef.scene.worldentity)
13760 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
13762 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
13763 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
13764 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
13766 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
13769 if (r_shownormals.value < 0)
13771 qglBegin(GL_LINES);
13772 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13774 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13775 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13776 qglVertex3f(v[0], v[1], v[2]);
13777 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
13778 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13779 qglVertex3f(v[0], v[1], v[2]);
13784 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
13786 qglBegin(GL_LINES);
13787 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13789 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13790 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13791 qglVertex3f(v[0], v[1], v[2]);
13792 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
13793 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13794 qglVertex3f(v[0], v[1], v[2]);
13798 qglBegin(GL_LINES);
13799 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13801 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13802 GL_Color(0, r_refdef.view.colorscale, 0, 1);
13803 qglVertex3f(v[0], v[1], v[2]);
13804 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
13805 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13806 qglVertex3f(v[0], v[1], v[2]);
13810 qglBegin(GL_LINES);
13811 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13813 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13814 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13815 qglVertex3f(v[0], v[1], v[2]);
13816 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
13817 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13818 qglVertex3f(v[0], v[1], v[2]);
13825 rsurface.texture = NULL;
13829 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
13830 int r_maxsurfacelist = 0;
13831 const msurface_t **r_surfacelist = NULL;
13832 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13834 int i, j, endj, flagsmask;
13835 dp_model_t *model = r_refdef.scene.worldmodel;
13836 msurface_t *surfaces;
13837 unsigned char *update;
13838 int numsurfacelist = 0;
13842 if (r_maxsurfacelist < model->num_surfaces)
13844 r_maxsurfacelist = model->num_surfaces;
13846 Mem_Free((msurface_t**)r_surfacelist);
13847 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13850 RSurf_ActiveWorldEntity();
13852 surfaces = model->data_surfaces;
13853 update = model->brushq1.lightmapupdateflags;
13855 // update light styles on this submodel
13856 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13858 model_brush_lightstyleinfo_t *style;
13859 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13861 if (style->value != r_refdef.scene.lightstylevalue[style->style])
13863 int *list = style->surfacelist;
13864 style->value = r_refdef.scene.lightstylevalue[style->style];
13865 for (j = 0;j < style->numsurfaces;j++)
13866 update[list[j]] = true;
13871 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13875 R_DrawDebugModel();
13876 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13880 rsurface.lightmaptexture = NULL;
13881 rsurface.deluxemaptexture = NULL;
13882 rsurface.uselightmaptexture = false;
13883 rsurface.texture = NULL;
13884 rsurface.rtlight = NULL;
13885 numsurfacelist = 0;
13886 // add visible surfaces to draw list
13887 for (i = 0;i < model->nummodelsurfaces;i++)
13889 j = model->sortedmodelsurfaces[i];
13890 if (r_refdef.viewcache.world_surfacevisible[j])
13891 r_surfacelist[numsurfacelist++] = surfaces + j;
13893 // update lightmaps if needed
13894 if (model->brushq1.firstrender)
13896 model->brushq1.firstrender = false;
13897 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13899 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13903 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13904 if (r_refdef.viewcache.world_surfacevisible[j])
13906 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13908 // don't do anything if there were no surfaces
13909 if (!numsurfacelist)
13911 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13914 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13916 // add to stats if desired
13917 if (r_speeds.integer && !skysurfaces && !depthonly)
13919 r_refdef.stats.world_surfaces += numsurfacelist;
13920 for (j = 0;j < numsurfacelist;j++)
13921 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
13924 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13927 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13929 int i, j, endj, flagsmask;
13930 dp_model_t *model = ent->model;
13931 msurface_t *surfaces;
13932 unsigned char *update;
13933 int numsurfacelist = 0;
13937 if (r_maxsurfacelist < model->num_surfaces)
13939 r_maxsurfacelist = model->num_surfaces;
13941 Mem_Free((msurface_t **)r_surfacelist);
13942 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13945 // if the model is static it doesn't matter what value we give for
13946 // wantnormals and wanttangents, so this logic uses only rules applicable
13947 // to a model, knowing that they are meaningless otherwise
13948 if (ent == r_refdef.scene.worldentity)
13949 RSurf_ActiveWorldEntity();
13950 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13951 RSurf_ActiveModelEntity(ent, false, false, false);
13953 RSurf_ActiveModelEntity(ent, true, true, true);
13954 else if (depthonly)
13956 switch (vid.renderpath)
13958 case RENDERPATH_GL20:
13959 case RENDERPATH_D3D9:
13960 case RENDERPATH_D3D10:
13961 case RENDERPATH_D3D11:
13962 case RENDERPATH_SOFT:
13963 case RENDERPATH_GLES2:
13964 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
13966 case RENDERPATH_GL13:
13967 case RENDERPATH_GL11:
13968 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
13974 switch (vid.renderpath)
13976 case RENDERPATH_GL20:
13977 case RENDERPATH_D3D9:
13978 case RENDERPATH_D3D10:
13979 case RENDERPATH_D3D11:
13980 case RENDERPATH_SOFT:
13981 case RENDERPATH_GLES2:
13982 RSurf_ActiveModelEntity(ent, true, true, false);
13984 case RENDERPATH_GL13:
13985 case RENDERPATH_GL11:
13986 RSurf_ActiveModelEntity(ent, true, false, false);
13991 surfaces = model->data_surfaces;
13992 update = model->brushq1.lightmapupdateflags;
13994 // update light styles
13995 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13997 model_brush_lightstyleinfo_t *style;
13998 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14000 if (style->value != r_refdef.scene.lightstylevalue[style->style])
14002 int *list = style->surfacelist;
14003 style->value = r_refdef.scene.lightstylevalue[style->style];
14004 for (j = 0;j < style->numsurfaces;j++)
14005 update[list[j]] = true;
14010 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14014 R_DrawDebugModel();
14015 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14019 rsurface.lightmaptexture = NULL;
14020 rsurface.deluxemaptexture = NULL;
14021 rsurface.uselightmaptexture = false;
14022 rsurface.texture = NULL;
14023 rsurface.rtlight = NULL;
14024 numsurfacelist = 0;
14025 // add visible surfaces to draw list
14026 for (i = 0;i < model->nummodelsurfaces;i++)
14027 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14028 // don't do anything if there were no surfaces
14029 if (!numsurfacelist)
14031 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14034 // update lightmaps if needed
14038 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14043 R_BuildLightMap(ent, surfaces + j);
14048 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14050 R_BuildLightMap(ent, surfaces + j);
14051 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14053 // add to stats if desired
14054 if (r_speeds.integer && !skysurfaces && !depthonly)
14056 r_refdef.stats.entities_surfaces += numsurfacelist;
14057 for (j = 0;j < numsurfacelist;j++)
14058 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14061 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14064 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14066 static texture_t texture;
14067 static msurface_t surface;
14068 const msurface_t *surfacelist = &surface;
14070 // fake enough texture and surface state to render this geometry
14072 texture.update_lastrenderframe = -1; // regenerate this texture
14073 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14074 texture.currentskinframe = skinframe;
14075 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14076 texture.offsetmapping = OFFSETMAPPING_OFF;
14077 texture.offsetscale = 1;
14078 texture.specularscalemod = 1;
14079 texture.specularpowermod = 1;
14081 surface.texture = &texture;
14082 surface.num_triangles = numtriangles;
14083 surface.num_firsttriangle = firsttriangle;
14084 surface.num_vertices = numvertices;
14085 surface.num_firstvertex = firstvertex;
14088 rsurface.texture = R_GetCurrentTexture(surface.texture);
14089 rsurface.lightmaptexture = NULL;
14090 rsurface.deluxemaptexture = NULL;
14091 rsurface.uselightmaptexture = false;
14092 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14095 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)
14097 static msurface_t surface;
14098 const msurface_t *surfacelist = &surface;
14100 // fake enough texture and surface state to render this geometry
14101 surface.texture = texture;
14102 surface.num_triangles = numtriangles;
14103 surface.num_firsttriangle = firsttriangle;
14104 surface.num_vertices = numvertices;
14105 surface.num_firstvertex = firstvertex;
14108 rsurface.texture = R_GetCurrentTexture(surface.texture);
14109 rsurface.lightmaptexture = NULL;
14110 rsurface.deluxemaptexture = NULL;
14111 rsurface.uselightmaptexture = false;
14112 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);